我试图将一个列表拆分为一系列较小的列表。

我的问题:我的拆分列表功能没有将它们拆分为正确大小的列表。它应该把它们分成大小为30的列表,但它却把它们分成大小为114的列表?

如何让我的函数将一个列表分割成X个大小为30或更小的列表?

public static List<List<float[]>> splitList(List <float[]> locations, int nSize=30) 
{       
    List<List<float[]>> list = new List<List<float[]>>();

    for (int i=(int)(Math.Ceiling((decimal)(locations.Count/nSize))); i>=0; i--) {
        List <float[]> subLocat = new List <float[]>(locations); 

        if (subLocat.Count >= ((i*nSize)+nSize))
            subLocat.RemoveRange(i*nSize, nSize);
        else subLocat.RemoveRange(i*nSize, subLocat.Count-(i*nSize));

        Debug.Log ("Index: "+i.ToString()+", Size: "+subLocat.Count.ToString());
        list.Add (subLocat);
    }

    return list;
}

如果我在144大小的列表上使用该函数,那么输出是:

指数:4,尺寸:120 指数:3,尺寸:114 指数:2,尺寸:114 指数:1,尺寸:114 索引:0,大小:114


当前回答

针对.NET 6的更新

var originalList = new List<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

// split into arrays of no more than three
IEnumerable<int[]> chunks = originalList.Chunk(3);

在。net 6之前

public static IEnumerable<IEnumerable<T>> SplitIntoSets<T>
    (this IEnumerable<T> source, int itemsPerSet) 
{
    var sourceList = source as List<T> ?? source.ToList();
    for (var index = 0; index < sourceList.Count; index += itemsPerSet)
    {
        yield return sourceList.Skip(index).Take(itemsPerSet);
    }
}

其他回答

在。net 6中,你可以使用source.Chunk(chunkSize)

一个基于Serj-Tm的公认答案的更通用的版本。

    public static IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> source, int size = 30)
    {
        var count = source.Count();
        for (int i = 0; i < count; i += size)
        {
            yield return source
                .Skip(Math.Min(size, count - i))
                .Take(size);
        }
    }

我发现公认的答案(Serj-Tm)是最健壮的,但我想建议一个通用版本。

public static List<List<T>> splitList<T>(List<T> locations, int nSize = 30)
{
    var list = new List<List<T>>();

    for (int i = 0; i < locations.Count; i += nSize)
    {
        list.Add(locations.GetRange(i, Math.Min(nSize, locations.Count - i)));
    }

    return list;
}
List<int> orginalList =new List<int>(){1,2,3,4,5,6,7,8,9,10,12};
Dictionary<int,List<int>> dic = new Dictionary <int,List<int>> ();
int batchcount = orginalList.Count/2; //To List into two 2 parts if you 
 want three give three
List<int> lst = new List<int>();
for (int i=0;i<orginalList.Count; i++)
{
lst.Add(orginalList[i]);
if (i % batchCount == 0 && i!=0)
{
Dic.Add(threadId, lst);
lst = new List<int>();**strong text**
threadId++;
}
}
if(lst.Count>0)
Dic.Add(threadId, lst); //in case if any dayleft 
foreach(int BatchId in Dic.Keys)
{
  Console.Writeline("BatchId:"+BatchId);
  Console.Writeline('Batch Count:"+Dic[BatchId].Count);
}

Serj-Tm解决方案很好,而且这是作为列表扩展方法的通用版本(将其放入静态类中):

public static List<List<T>> Split<T>(this List<T> items, int sliceSize = 30)
{
    List<List<T>> list = new List<List<T>>();
    for (int i = 0; i < items.Count; i += sliceSize)
        list.Add(items.GetRange(i, Math.Min(sliceSize, items.Count - i)));
    return list;
} 

如果你想用条件而不是固定的数字来分割它:

///<summary>
/// splits a list based on a condition (similar to the split function for strings)
///</summary>
public static IEnumerable<List<T>> Split<T>(this IEnumerable<T> src, Func<T, bool> pred)
{
    var list = new List<T>();
    foreach(T item in src)
    {   
        if(pred(item))
        {
            if(list != null && list.Count > 0)
                yield return list;
                
            list = new List<T>();
        }
        else
        {
            list.Add(item);
        }
    }
}