C# 使用LINQ查找与条件匹配的元素的第一个索引
我希望能够找到返回的元素的索引,事实上,在我的例子中,我只需要一个索引,这样我就可以将.Skip()插入到列表中C# 使用LINQ查找与条件匹配的元素的第一个索引,c#,linq,C#,Linq,我希望能够找到返回的元素的索引,事实上,在我的例子中,我只需要一个索引,这样我就可以将.Skip()插入到列表中 有没有办法在IEnumerable中实现这一点?我不想为此使用列表,但它确实有一个FindIndex()方法您可以首先投影列表项及其索引: var item = list.Where(t => somecondition); 当然,这很简单: var item = list.Select((item, index) => new { Item = item, Index
有没有办法在IEnumerable中实现这一点?我不想为此使用
列表
,但它确实有一个FindIndex()
方法您可以首先投影列表项及其索引:
var item = list.Where(t => somecondition);
当然,这很简单:
var item = list.Select((item, index) => new { Item = item, Index = index })
.Where(pair => SomeCondition(pair.Item))
.Select(result => result.Index);
如果找到任何匹配项,则返回索引,否则返回-1。+1和-1用于获取没有匹配项的情况下的行为。如果你知道总会有一场比赛,那就更简单了:
var index = list.Select((value, index) => new { value, index = index + 1 })
.Where(pair => SomeCondition(pair.value))
.Select(pair => pair.index)
.FirstOrDefault() - 1;
如果你很高兴从这一点开始就得到了列表的其余部分,SkipWhile
绝对是你的朋友,正如Chris所提到的。如果您想要列表的其余部分和原始索引,也很容易:
var index = list.Select((value, index) => new { value, index })
.Where(pair => SomeCondition(pair.value))
.Select(pair => pair.index)
.FirstOrDefault();
这将为您提供一系列的
{value,index}
对,从第一个匹配SomeCondition
的值开始,当然可以使用IEnumerable
var query = list.Select((value, index) => new { value, index })
.SkipWhile(pair => !SomeCondition(pair.value))
公共静态类EnumerableExtension
{
公共静态int FirstIndexMatch(此IEnumerable items,Func matchCondition)
{
var指数=0;
foreach(项目中的var项目)
{
if(匹配条件调用(项))
{
收益指数;
}
索引++;
}
返回-1;
}
}
我需要更多的上下文,但如果您只是获取一个索引以便调用.Skip
,我建议您在.SkipWhile
时查看一下.SkipWhile>
如果您确实需要索引,我建议您编写自己的.IndexOf
扩展方法。如果您确实只需要第一个索引,请计算不匹配的索引:
public static class EnumerableExtension
{
public static int FirstIndexMatch<TItem>(this IEnumerable<TItem> items, Func<TItem,bool> matchCondition)
{
var index = 0;
foreach (var item in items)
{
if(matchCondition.Invoke(item))
{
return index;
}
index++;
}
return -1;
}
}
如果你知道你有一个列表,而不是像IEnumerable或IQueryable这样的东西,这可能会很好
var index = list.TakeWhile(t => !someCondition).Count()
public static int IndexOf(此IList源代码,Func条件)
{
for(int i=0;i
参考Jon Skeet的答案,您可以在调用FirstOrDefault之前使用DefaultIfEmpty(),而无需对索引进行加减
public static int IndexOf<T>(this IList<T> source, Func<T, bool> condition)
{
for (int i = 0; i < source.Count; i++)
if (condition(source[i]))
return i;
return -1;
}
+1提到他可能想在SkipWhile
时使用SkipWhile,因为找到索引然后调用Skip
将枚举查询两次以关闭。。。现在我想将SkipWhile与计数器结合使用,即list.SkipWhile(myBusinessLogicCondition&&list.Count-SkipIndex>someXnumber);user494352:看起来你想看看Jon的列表。Select().SkipWhile()
在他的帖子末尾回答。谢谢Gabe,我在看@VStudio,可能有一种方法可以在SkipWhile本身中实现这一点,看起来SkipWhile的超负荷确实有一个索引。是的,有一个超负荷的.SkipWhile为您提供索引。例如:list.SkipWhile((值,索引)=>myBusinessLogicCondigion(值)&&list.Count-index>someXnumber);不过,这确实让人觉得非常必要:-)很遗憾,FirstOrDefault
不允许您指定默认值,是吗?谢谢Jon,我正在尝试将SkipWhile与索引合并,而不是计数,以查看我是否跳过了太多。如果您将索引强制转换为可为null,则生成的FirstOrDefault将是可为null的…新的{value,index=(int?)index+1})旧答案/问题我知道,但这完美地说明了为什么Linq不是宇宙中所有问题的正确答案。+1.我通常更喜欢像Jon那样的Linq-y答案,但在这种情况下,这个解决方案更容易查看和理解它的功能。作为一种扩展方法,它仍然可以用于Linq表达式中。双赢。使用matchCondition.Invoke(item)
是不必要的。你可以只做matchCondition(item)
。如果没有匹配会发生什么。结果不是列表的长度吗?是的,这是一个很好的观点!如果你使用上面的代码,应该验证索引是否小于列表的长度
var index = list.Select((value, index) => new { value, index })
.Where(pair => SomeCondition(pair.value))
.Select(pair => pair.index).DefaultIfEmpty(-1)
.FirstOrDefault();