475 Stimmen

Liste in Unterlisten aufteilen mit LINQ

Gibt es eine Möglichkeit, wie ich eine List<SomeObject> in mehrere separate Listen von SomeObject und dabei den Artikelindex als Trennzeichen für jeden Split?

Lassen Sie mich ein Beispiel geben:

Ich habe eine List<SomeObject> und ich brauche eine List<List<SomeObject>> o List<SomeObject>[] , so dass jede dieser resultierenden Listen eine Gruppe von 3 Elementen der ursprünglichen Liste (in der Reihenfolge) enthält.

z. B.:

  • Ursprüngliche Liste: [a, g, e, w, p, s, q, f, x, y, i, m, c]

  • Daraus resultierende Listen: [a, g, e], [w, p, s], [q, f, x], [y, i, m], [c]

Außerdem muss die Größe der resultierenden Liste ein Parameter dieser Funktion sein.

3voto

Jobo Punkte 970

Wenn die Liste vom Typ system.collections.generic ist, können Sie die Methode "CopyTo" verwenden, um Elemente Ihres Arrays in andere Unterarrays zu kopieren. Sie geben das Startelement und die Anzahl der zu kopierenden Elemente an.

Sie können auch 3 Klone Ihrer ursprünglichen Liste erstellen und die Funktion "RemoveRange" für jede Liste verwenden, um die Liste auf die gewünschte Größe zu verkleinern.

Oder erstellen Sie einfach eine Hilfsmethode, die dies für Sie erledigt.

3voto

Bertrand Punkte 583

Es ist eine alte Lösung, aber ich hatte einen anderen Ansatz. Ich verwende Skip um den gewünschten Versatz anzufahren und Take um die gewünschte Anzahl von Elementen zu extrahieren:

public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, 
                                                   int chunkSize)
{
    if (chunkSize <= 0)
        throw new ArgumentOutOfRangeException($"{nameof(chunkSize)} should be > 0");

    var nbChunks = (int)Math.Ceiling((double)source.Count()/chunkSize);

    return Enumerable.Range(0, nbChunks)
                     .Select(chunkNb => source.Skip(chunkNb*chunkSize)
                     .Take(chunkSize));
}

2voto

dek Punkte 75

Die Frage war, wie man " Liste in Unterlisten aufteilen mit LINQ "Manchmal möchten Sie jedoch, dass diese Unterlisten auf die Originalliste verweisen und keine Kopien sind. So können Sie die Originalliste von den Unterlisten aus ändern. In diesem Fall kann dies für Sie funktionieren.

public static IEnumerable<Memory<T>> RefChunkBy<T>(this T[] array, int size)
{
    if (size < 1 || array is null)
    {
        throw new ArgumentException("chunkSize must be positive");
    }

    var index = 0;
    var counter = 0;

    for (int i = 0; i < array.Length; i++)
    {
        if (counter == size)
        {
            yield return new Memory<T>(array, index, size);
            index = i;
            counter = 0;
        }
        counter++;

        if (i + 1 == array.Length)
        {
            yield return new Memory<T>(array, index, array.Length - index);
        }
    }
}

Verwendung:

var src = new[] { 1, 2, 3, 4, 5, 6 };

var c3 = RefChunkBy(src, 3);      // {{1, 2, 3}, {4, 5, 6}};
var c4 = RefChunkBy(src, 4);      // {{1, 2, 3, 4}, {5, 6}};

// as extension method
var c3 = src.RefChunkBy(3);      // {{1, 2, 3}, {4, 5, 6}};
var c4 = src.RefChunkBy(4);      // {{1, 2, 3, 4}, {5, 6}};

var sum = c3.Select(c => c.Span.ToArray().Sum());    // {6, 15}
var count = c3.Count();                 // 2
var take2 = c3.Select(c => c.Span.ToArray().Take(2));  // {{1, 2}, {4, 5}}

Sie können diesen Code gerne verbessern.

2voto

frhack Punkte 4410

Eine andere Möglichkeit ist die Verwendung von Rx Puffer-Operator

//using System.Linq;
//using System.Reactive.Linq;
//using System.Reactive.Threading.Tasks;

var observableBatches = anAnumerable.ToObservable().Buffer(size);

var batches = aList.ToObservable().Buffer(size).ToList().ToTask().GetAwaiter().GetResult();

1voto

Janosz G. Punkte 11

Modulare Partitionierung verwenden:

public IEnumerable<IEnumerable<string>> Split(IEnumerable<string> input, int chunkSize)
{
    var chunks = (int)Math.Ceiling((double)input.Count() / (double)chunkSize);
    return Enumerable.Range(0, chunks).Select(id => input.Where(s => s.GetHashCode() % chunks == id));
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X