C# 在列表中每隔2个对象取一个
我有一个IEnumerable,我想得到一个包含每n个元素的新IEnumerableC# 在列表中每隔2个对象取一个,c#,.net,linq,linq-to-objects,C#,.net,Linq,Linq To Objects,我有一个IEnumerable,我想得到一个包含每n个元素的新IEnumerable 这可以在Linq中完成吗 我自己就知道了 IEnumerable.Where()方法有一个重载,它获取当前元素的索引-这正是医生所要求的 (new []{1,2,3,4,5}).Where((elem, idx) => idx % 2 == 0); 这会回来的 {1, 3, 5} 更新:为了涵盖我的用例和Dan Tao的建议,让我们也指定第一个返回的元素应该是什么: var firstIdx = 1;
这可以在Linq中完成吗 我自己就知道了
IEnumerable.Where()
方法有一个重载,它获取当前元素的索引-这正是医生所要求的
(new []{1,2,3,4,5}).Where((elem, idx) => idx % 2 == 0);
这会回来的
{1, 3, 5}
更新:为了涵盖我的用例和Dan Tao的建议,让我们也指定第一个返回的元素应该是什么:
var firstIdx = 1;
var takeEvery = 2;
var list = new []{1,2,3,4,5};
var newList = list
.Skip(firstIdx)
.Where((elem, idx) => idx % takeEvery == 0);
…会回来的
{2, 4}
实施:
虽然不是LINQ,但您也可以使用
yield
创建扩展方法
public static IEnumerable<T> EverySecondObject<T>(this IEnumerable<T> list)
{
using (var enumerator = list.GetEnumerator())
{
while (true)
{
if (!enumerator.MoveNext())
yield break;
if (enumerator.MoveNext())
yield return enumerator.Current;
else
yield break;
}
}
}
公共静态IEnumerable EverySecondObject(此IEnumerable列表)
{
使用(var enumerator=list.GetEnumerator())
{
while(true)
{
如果(!enumerator.MoveNext())
屈服断裂;
if(枚举数.MoveNext())
产生返回枚举数。当前;
其他的
屈服断裂;
}
}
}
我第一次看到索引在集合谓词bravo中的实际使用,我不会想到这一点。你可以定义一个返回此值的扩展方法。其中(…)可以在你的应用程序中更清楚地说明这一点。我可能建议使用idx+1
来匹配“每n个元素”的描述;至少对我来说,这表明返回的第一个元素应该是第n个元素。所以{1,2,3,4,5}
中的每一个第二个元素对我来说意味着{2,4}
(你的代码返回{1,3,5}
)。也许这是主观的。@Dan Tao:听过这个吗?“为什么狗和工程师是一样的?-他们都有一双聪明的眼睛,谁也不会说话。”。我的代码做了我希望它做的事情,我只是没能正确地解释:)你也可以跳过数组,使用Enumerable.Range(1,10)
@Anthony:这只是一个示例,旨在让你立即理解。我知道有些开发人员必须查找可枚举的.Range
。使用将其包装在中!(IEnumerable
继承了IDisposable
)@Dan:你是说IEnumerator。为什么我以前从未意识到这一点?是的,我的意思是IEnumerator
。哎呀!(出于某种原因,当我想键入另一个时,我总是键入一个。一定是肌肉记忆。)奇怪的是,IEnumerator继承了IDisposable,但IEnumerator没有。不知道为什么。
var upToTen = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evens = upToTen.Sample(2);
var multiplesOfThree = upToTen.Sample(3);
public static IEnumerable<T> EverySecondObject<T>(this IEnumerable<T> list)
{
using (var enumerator = list.GetEnumerator())
{
while (true)
{
if (!enumerator.MoveNext())
yield break;
if (enumerator.MoveNext())
yield return enumerator.Current;
else
yield break;
}
}
}