我尝试从字符串列表中一次取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个项目(String 1,2和3),第二次我希望有这3个项目(String 4,5和6)。但是当我运行这个currRows时,只包含例如“String 1”,这是逐字符分割的?!
我在这里缺少什么?
答案 0 :(得分:2)
x.ToList();
正在string
上调用该方法。 string
是IEnumerable<char>
,因此currRows
的结果是字符列表。您可以完全删除该行,并在第二个循环中使用x
。ToList()
循环中使用的集合上执行此操作,则使用foreach
通常是[1]无意义的操作。它将迭代您的集合并构建一个新列表,然后进行迭代。您可以从第一个循环中删除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);
}
}
需要大量改进的空间,但它应该让您了解应该如何处理这项任务。
答案 1 :(得分:2)
但是当我运行这个currRows只包含例如“String 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)
{
}
}
另一种可能性是自己创建扩展方法。这取自this answer:
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));
}
}
答案 2 :(得分:0)
从您的代码开始:
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)
{
}
}
但肯定这可以再次简化为thingYouAreLoopingOver只是listOfStrings的前三个东西,所以我们有:
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)
{
}
}
现在应该清楚为什么你会得到你所看到的行为。