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

use*_*352 36 c# linq

var item = list.Where(t => somecondition);
Run Code Online (Sandbox Code Playgroud)

我希望能够找到返回的元素的索引,事实上,在我的情况下,我想要的只是一个索引,这样我就可以将.Skip()放到列表中了.

有没有办法在IEnumerable中执行此操作?我讨厌使用一个List<T>,但这确实有一个FindIndex()方法

Jon*_*eet 45

当然,这很简单:

var index = list.Select((value, index) => new { value, index = index + 1 })
                .Where(pair => SomeCondition(pair.value))
                .Select(pair => pair.index)
                .FirstOrDefault() - 1;
Run Code Online (Sandbox Code Playgroud)

如果找到匹配的东西,那将返回索引,否则返回-1.+1和-1是为了获得没有匹配的情况的行为.如果你知道总会有匹配,那就更简单了:

var index = list.Select((value, index) => new { value, index })
                .Where(pair => SomeCondition(pair.value))
                .Select(pair => pair.index)
                .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

如果你很高兴从那一点开始获得列表的其余部分,那SkipWhile肯定是你的朋友,正如克里斯所提到的那样.如果想要列表的其余部分原始索引,那也很容易:

var query = list.Select((value, index) => new { value, index })
                .SkipWhile(pair => !SomeCondition(pair.value))
Run Code Online (Sandbox Code Playgroud)

这将为您提供{ value, index }第一个值匹配的一系列对SomeCondition.

  • 遗憾的是 `FirstOrDefault` 不允许您指定默认值,不是吗? (2认同)
  • 我知道旧的答案/问题,但这完美地说明了为什么 Linq 不是宇宙中每个问题的正确答案。 (2认同)

Gar*_*eth 43

如果你真的只需要第一个索引,那么计算那些不匹配的索引:

var index = list.TakeWhile(t => !someCondition).Count()
Run Code Online (Sandbox Code Playgroud)

  • 如果没有匹配会发生什么。结果不是列表的长度吗? (2认同)

Chr*_*nos 26

我需要更多的上下文,但如果你只是得到一个索引以便你可以打电话.Skip,我建议你去看看.SkipWhile.

如果您确实需要索引,我建议您编写自己的.IndexOf扩展方法.


Man*_*ani 17

当然可以使用IEnumerable ...

 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 没有必要使用“matchCondition.Invoke(item)”。你可以只做“matchCondition(item)”。 (4认同)
  • +1。我通常更喜欢Jon's的linq-y答案,但是在这种情况下,这种解决方案非常容易观察和理解它的作用。作为扩展方法,它仍然可以在linq表达式中*使用*。双赢。 (2认同)

Fré*_*idi 8

您可以首先使用索引投影列表项:

var item = list.Select((item, index) => new { Item = item, Index = index })
               .Where(pair => SomeCondition(pair.Item))
               .Select(result => result.Index);
Run Code Online (Sandbox Code Playgroud)