用循环处理一个列表,每次取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?
有没有一种方法可以使用循环获取大列表中的前 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?