C# 使用LINQ查找与条件匹配的元素的第一个索引

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

我希望能够找到返回的元素的索引,事实上,在我的例子中,我只需要一个索引,这样我就可以将.Skip()插入到列表中


有没有办法在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();