0

List<T>a を異なるチャンクサイズの のリストに分割する次の拡張メソッドがありますが、List<T>その効率性には疑問があります。それを改善するために私にできることはありますか、それともそのままでいいですか?

public static List<List<T>> Split<T>(this List<T> source, params int[] chunkSizes)
{
    int totalSize = chunkSizes.Sum();
    int sourceCount = source.Count();
    if (totalSize > sourceCount)
    {
        throw new ArgumentException("Sum of chunk sizes is larger than the number of elements in source.", "chunkSizes");
    }

    List<List<T>> listOfLists = new List<List<T>>(chunkSizes.Length);
    int index = 0;
    foreach (int chunkSize in chunkSizes)
    {
        listOfLists.Add(source.GetRange(index, chunkSize));
        index += chunkSize;
    }

    // Get the entire last part if the total size of all the chunks is less than the actual size of the source
    if (totalSize < sourceCount)
    {
        listOfLists.Add(source.GetRange(index, sourceCount - totalSize));
    }

    return listOfLists;
}

コードの使用例:

List<int> list = new List<int> { 1,2,4,5,6,7,8,9,10,12,43,23,453,34,23,112,4,23 };
var result =  list.Split(2, 3, 3, 2, 1, 3);
Console.WriteLine(result);

これにより、望ましい結果が得られ、チャンクの合計サイズがリストのサイズよりも 4 小さいため、最終的なリスト部分は 4 つの数字になります。

GetRangeこれは同じソースを何度も列挙しているだけなのではないかと心配しているので、私は特にその部分を疑っています...

編集:ソースを一度列挙する方法を知っていると思います: ソース自体で foreach を実行し、反復された要素の数が現在のチャンクサイズと同じかどうかを確認し続けます。その場合、新しいリストを追加して、次のチャンクサイズに進みます。考え?

4

2 に答える 2

1

このコードにはパフォーマンスの問題はありません。はO(chunkSize)であると文書化されており、の最も重要なプロパティの1つは、 O(1)のインデックス付けを可能にすることであるGetRangeため、これも簡単に推測できます。List<T>

そうは言っても、次のようなLINQ-yバージョンのコードを書くことができます。

var rangeStart = 0;
var ranges = chunkSizes.Select(n => Tuple.Create((rangeStart += n) - n, n))
                       .ToArray();
var lists = ranges.Select(r => source.GetRange(r.Item1, r.Item2)).ToList();

if (rangeStart < source.Count) {
    lists.Last().AddRange(source.Skip(rangeStart));
}

return lists;
于 2013-01-15T12:13:37.340 に答える
0

この拡張メソッドを使用して、指定されたチャンク サイズでソース リストをサブリストにチャンクすることをお勧めします。

using System.Collections.Generic;
using System.Linq;

...

/// <summary>
/// Helper methods for the lists.
/// </summary>
public static class ListExtensions
{
    public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize) 
    {
        return source
            .Select((x, i) => new { Index = i, Value = x })
            .GroupBy(x => x.Index / chunkSize)
            .Select(x => x.Select(v => v.Value).ToList())
            .ToList();
    }
}
于 2014-06-06T17:04:45.217 に答える