C# 为什么这个可枚举列表会分裂?
我试图从一个字符串列表中一次提取3行,但它没有按预期工作。考虑这个代码…C# 为什么这个可枚举列表会分裂?,c#,linq,ienumerable,C#,Linq,Ienumerable,我试图从一个字符串列表中一次提取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
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=新列表
{
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”
};
foreach(listofstring.Take(3.ToList()中的变量x)
{
var currRows=x.ToList();
//Currows应该有3项
foreach(以当前行为单位的var itm)
{
}
}
第一次运行时,我希望currRows包含3项(字符串1、2和3),第二次运行时,我希望包含这3项(字符串4、5和6)。但是当我运行这个命令时,行只包含例如“string1”,这是一个字符一个字符分割的
我错过了什么
x.ToList()
正在对字符串
调用该方法。string
是一个IEnumerable
,因此currows
的结果是一个字符列表。您可以完全删除该行,并在第二个循环中使用x
foreach
循环中使用的集合上使用ToList()
通常是[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);
}
}
var listOfStrings=新列表
{
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”
};
int步长=0;
常量int numTake=3;
对于(var i=0;i
有很大的改进空间,但它应该让你知道如何完成这项任务
Enumerable.Take
将从IEnumerable
中获取请求的项目数量。这使得x
变量的类型为string
,您稍后将其调用为ToList()
,从而有效地创建了一个列表
,这不是您想要的
您可以使用它的批处理
扩展方法,它完全满足您的需要。它返回一个IEnumerable
:
foreach(listofstring.batch(3)中的变量批)
{
//batch是一个IEnumerable,将有3项。
foreach(批量中的var项目)
{
}
}
另一种可能性是自己创建扩展方法。这是取自:
公共静态类EnumerableExtensions
{
公共静态IEnumerable批处理(此IEnumerable项,
整数(最大项)
{
返回项。选择((项,inx)=>new{item,inx})
.GroupBy(x=>x.inx/maxItems)
.Select(g=>g.Select(x=>x.item));
}
}
从您的代码开始:
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=新列表
{
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”
};
foreach(listofstring.Take(3.ToList()中的变量x)
{
var currRows=x.ToList();
//Currows应该有3项
foreach(以当前行为单位的var itm)
{
}
}
让我们通过为正在循环的内容创建一个额外变量来简化代码:
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)
{
}
}
var listOfStrings=新列表
{
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”
};
var thingsyouarelopingover=listofstring.Take(3.ToList();
foreach(在thingsYouAreLoopingOver中的变量x)
{
var currRows=x.ToList();
//Currows应该有3项
foreach(以当前行为单位的var itm)
{
}
}
但这当然可以再次简化,因为您正在循环的内容只是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)
{
}
}
var thingsyouarelopingover=新列表
{
“字符串1”,
“字符串2”,
“字符串3”
};
foreach(在thingsYouAreLoopingOver中的变量x)
{
var currRows=x.ToList();
//Currows应该有3项
foreach(以当前行为单位的var itm)
{
}
}
现在应该清楚你为什么会看到这种行为。这不是
Take
的工作原理。或者任何其他LINQ操作符,真的-他们从不修改原始集合。例如,您需要使用Take
和Skip
的组合。将第二个循环替换为foreach(x中的var-itm)
。不要对字符串调用ToList()
,因为它也是IEnumerable
,因此string.ToList()
返回字符列表。其次,删除第一个循环中的ToList()
调用,它什么也不做,而且浪费了CPU和内存。最后,Take(3)
只取前3项,不按3分组。谢谢,MoreLinq确实非常方便。谢谢你解释为什么它没有像我预期的那样工作。
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)
{
}
}
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)
{
}
}