用循环处理一个列表,每次取100个元素,列表末尾自动小于100

Process a list with a loop, taking 100 elements each time and automatically less than 100 at the end of the list

有没有一种方法可以使用循环获取大列表中的前 100 个项目,对它们做一些处理,然后再处理下 100 个等等,但是当它接近尾声时,它会自动将“100”步骤缩短为剩余的物品。

目前我必须使用两个 if 循环:

for (int i = 0; i < listLength; i = i + 100)
{
    if (i + 100 < listLength)
    {
        //Does its thing with a bigList.GetRange(i, 100)
    }
    else
    {
        //Does the same thing with bigList.GetRange(i, listLength - i)
    }
}

有更好的方法吗?如果没有,我至少会让 "thing" 成为一个函数,这样代码就不必复制两次。

您可以为终点保留一个显式变量:

for (int i = 0, j; i < listLength; i = j)
{
    j = Math.min(listLength, i + 100);
    // do your thing with bigList.GetRange(i, j)
}

您可以使用 LINQ Skip and Take,您的代码会更简洁。

for (int i = 0; i < listLength; i=i+100)
{
    var items = bigList.Skip(i).Take(100); 
    // Do something with 100 or remaining items
}

注意:如果物品少于100件Take会给你剩余的。

List<int> list = null;
int amount_of_hundreds = Math.Floor(list.Count/100);
int remaining_number = list.Count - (amount_of_hundreds * 100);

for(int i = 0; i < amount_of_hundreds; ++i)
    {
    for(int j = 0; j < 100; ++j)
        {
        int item = list[(i * 100) + j];
        // do what you want with item
        }
    }

 for(int i = 0; i < remaining_number; ++i)
    {
    int item = list[(amount_of_hundreds * 100) + i];
    // do what you want with item
    }

我不喜欢列出的任何答案,所以我做了自己的扩展:

public static class IEnumerableExtensions
{
    public static IEnumerable<IEnumerable<T>> MakeGroupsOf<T>(this IEnumerable<T> source, int count)
    {
        var grouping = new List<T>();
        foreach (var item in source)
        {
            grouping.Add(item);
            if(grouping.Count == count)
            {
                yield return grouping;
                grouping = new List<T>();
            }
        }

        if (grouping.Count != 0)
        {
            yield return grouping;
        }
    }
}

然后就可以使用了:

foreach(var group in allItems.MakeGroupsOf(100))
{
    // Do something
}

您也可以尝试以下方法:

        int i = 1;
        foreach (item x in bigList)
        {

            batchOperation.Insert(x); //replace it with your action; create the batch
            i++;
            if (i >100)
            {
                table.ExecuteBatch(batchOperation); //execute the batch
                batchOperation.Clear();
                i = 1; // re-initialize 
            }

        }

        if (batchOperation.Count >= 1 )
        {
            table.ExecuteBatch(batchOperation); //do this for the residue items 
        }

这是我的解决方案,首先,我在到达数组顶部后跳过最后一行(行 - skiplast)。

    [TestMethod]
    public void SkipTake()
    {
        var rows = 100;
        var skip = 1;
        var skiplast = 95;
        var result = Enumerable.Range(1, rows).Take(rows - skiplast).Skip(skip - 1 == 0 ? 1 : skip).ToList();
    }

你可以将一个大列表按限制分割成多个小列表,像这样:

var limit = 100;
foreach (var smallList in bigList.Select((x, i) => new { Index = i, Value = x })
                                 .GroupBy(x => x.Index / limit)
                                 .Select(x => x.Select(v => v.Value).ToList())
                                 .ToList())
{
    Console.WriteLine($"{smallList.Count}");
    Console.WriteLine(String.Join("\r\n", smallList));
}

在 dotnet 6 中你可以使用 chunk:

//Child collections will be comprised of 10 elements each.
IEnumerable<int[]> sublists = numbers.Chunk(10); 

https://exceptionnotfound.net/bite-size-dotnet-6-chunk-in-linq/

还有一个使用 group by 的参考,这对于旧版本的框架来说是一个非常有趣的解决方案: Split a collection into `n` parts with LINQ?