LINQ查找值的数组索引

Dan*_*inu 48 c# linq

假设我有以下字符串数组:

string[] str = new string[] {"max", "min", "avg", "max", "avg", "min"}
Run Code Online (Sandbox Code Playgroud)

是否可以使用LINQ获取与一个字符串匹配的索引列表?

作为一个例子,我想搜索字符串"avg"并获得一个包含的列表

2,4

意思是"avg"可以在str [2]和str [4]中找到.

rec*_*ive 98

.Select有一个很少使用的重载,产生一个索引.你可以像这样使用它:

str.Select((s, i) => new {i, s})
    .Where(t => t.s == "avg")
    .Select(t => t.i)
    .ToList()
Run Code Online (Sandbox Code Playgroud)

结果将是包含2和4的列表.

文档在这里

  • 请注意,[`Where`](http://msdn.microsoft.com/en-us/library/bb549418.aspx)也提供了重载. (9认同)

das*_*ght 15

你可以这样做:

str.Select((v,i) => new {Index = i, Value = v}) // Pair up values and indexes
   .Where(p => p.Value == "avg") // Do the filtering
   .Select(p => p.Index); // Keep the index and drop the value
Run Code Online (Sandbox Code Playgroud)

关键步骤是使用过载Select来为您的仿函数提供当前索引.


Tim*_*ter 6

您可以使用Enumerable.Select传递索引的重载,然后使用Enumerable.Where匿名类型:

List<int> result = str.Select((s, index) => new { s, index })
                      .Where(x => x.s== "avg")
                      .Select(x => x.index)
                      .ToList();
Run Code Online (Sandbox Code Playgroud)

如果您只想查找第一个/最后一个索引,还有内置方法List.IndexOfList.LastIndexOf:

int firstIndex = str.IndexOf("avg");
int lastIndex = str.LastIndexOf("avg");
Run Code Online (Sandbox Code Playgroud)

(或者你可以使用这个带有起始索引来指定起始位置的重载)


Bra*_*der 6

首先,您的代码实际上并没有迭代列表两次,它只迭代一次。

也就是说,您的 Select 实际上只是获取所有索引的序列;使用 Enumerable.Range 可以更轻松地完成此操作:

 var result = Enumerable.Range(0, str.Count)
                 .Where(i => str[i] == "avg")
                 .ToList();
Run Code Online (Sandbox Code Playgroud)

理解为什么列表实际上没有迭代两次需要一些时间来适应。我将尝试给出一个基本的解释。

您应该将大多数 LINQ 方法(例如 Select 和Where)视为管道。每种方法都会做一些微小的工作。在 Select 的情况下,你给它一个方法,它本质上是说,“每当有人问我下一个项目时,我会首先向我的输入序列询问一个项目,然后使用我必须将其转换为其他内容的方法,然后把那个物品交给使用我的人。” 或多或少是在说,“每当有人向我索要一个项目时,我都会向我的输入序列询问一个项目,如果该函数说它很好,我会传递它,如果不是,我会继续索要项目直到我得到一个通过的。”

因此,当您链接它们时,会发生 ToList 请求第一项的情况,它会转到Where to 作为它的第一项,Where 转到 Select 并询问它的第一项,Select 转到列表并询问它的第一项物品。然后列表提供它的第一项。Select 然后将该项目转换为它需要吐出的内容(在本例中,只是 int 0)并将其提供给Where。Where 获取该项目并运行它的函数,该函数确定它是真的,因此将 0 吐出到 ToList,这将其添加到列表中。整个事情又发生了 9 次。这意味着 Select 最终将只要求列表中的每个项目一次,并且会将每个结果直接提供给Where,后者会将“通过测试”的结果直接提供给ToList,ToList 将它们存储在列表中。所有 LINQ 方法都经过精心设计,只迭代源序列一次(当它们被迭代一次时)。

请注意,虽然乍一看这对您来说似乎很复杂,但实际上计算机可以轻松完成所有这些工作。它实际上并不像乍看起来那样对性能要求很高。