为什么这个可枚举列表分裂了?
本文关键字:分裂 列表 枚举 为什么 | 更新日期: 2023-09-27 18:17:47
我尝试一次从字符串列表中取出3行,但它没有按预期工作。考虑以下代码:
var listOfStrings = new List<string>
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5",
"String 6"
};
foreach (var x in listOfStrings.Take(3).ToList())
{
var currRows = x.ToList();
// currRows should have 3 items
foreach (var itm in currRows)
{
}
}
第一次运行时,我希望currRows有3个项目(字符串1,2和3),第二次我希望有这3个项目(字符串4,5和6)。但是当我运行这个currRows只包含例如"字符串1",这是按字符分割的?!
我在这里错过了什么?
但是当我运行这个currRows只包含例如"字符串1"和这是一个角色一个角色的分割吗!
这是因为Enumerable.Take
将从IEnumerable<T>
中获取所请求的项目数量。这使得您的x
变量为string
类型,稍后您将其称为ToList()
,从而有效地创建了List<char>
,这不是您想要的。
你可以使用MoreLINQ,它有一个Batch
扩展方法,这正是你想要的。它返回一个IEnumerable<IEnumerable<T>>
:
foreach (var batch in listOfStrings.Batch(3))
{
// batch is an IEnumerable<T>, and will have 3 items.
foreach (var item in batch)
{
}
}
另一种可能性是自己创建该扩展方法。
public static class EnumerableExtensions
{
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items,
int maxItems)
{
return items.Select((item, inx) => new { item, inx })
.GroupBy(x => x.inx / maxItems)
.Select(g => g.Select(x => x.item));
}
}
-
x.ToList();
正在string
上调用该方法。string
是IEnumerable<char>
,所以currRows
的结果是一个字符列表。您可以完全删除该行,并在第二个循环中使用x
。 - 使用
ToList()
通常是[1]一个毫无意义的操作,如果你在foreach
循环中使用的集合上做它。它将迭代您的集合并构造一个新的列表,然后迭代该列表。你可以从你的第一个循环中删除ToList
,它会表现得更好,但结果相同。 -
Take
仅取n
项数,不按n
项分组。
试试这个:
var listOfStrings = new List<string>
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5",
"String 6"
};
int step = 0;
const int numTake = 3;
for(var i = 0; i < listOfStrings.Count / numTake; i++)
{
Console.WriteLine("Starting a group!");
foreach (var x in listOfStrings.Skip(3 * step++).Take(3))
{
Console.WriteLine(x);
}
}
有很大的改进空间,但它应该给你一个你应该如何处理这个任务的想法。
- 有的情况下,你需要这样做-但你很可能不会遇到他们,当开始使用LINQ。
从代码开始:
var listOfStrings = new List<string>
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5",
"String 6"
};
foreach (var x in listOfStrings.Take(3).ToList())
{
var currRows = x.ToList();
// currRows should have 3 items
foreach (var itm in currRows)
{
}
}
让我们通过为循环创建一个额外的变量来简化代码:
var listOfStrings = new List<string>
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5",
"String 6"
};
var thingsYouAreLoopingOver = listOfStrings.Take(3).ToList();
foreach (var x in thingsYouAreLoopingOver)
{
var currRows = x.ToList();
// currRows should have 3 items
foreach (var itm in currRows)
{
}
}
当然这可以再一次简化为thingsYouAreLoopingOver只是listofstring的前三件事,所以我们有:
var thingsYouAreLoopingOver = new List<string>
{
"String 1",
"String 2",
"String 3"
};
foreach (var x in thingsYouAreLoopingOver)
{
var currRows = x.ToList();
// currRows should have 3 items
foreach (var itm in currRows)
{
}
}
现在你应该清楚为什么你会得到你所看到的行为。