使用LINQ查询获取索引值的集合

有一个更好的方法吗?

string[] s = {"zero", "one", "two", "three", "four", "five"}; var x = s .Select((a,i) => new {Value = a, Index = i}) .Where(b => b.Value.StartsWith("t")) .Select(c => c.Index); 

即我正在寻找一种更有效或更优雅的方式来获得符合标准的物品的位置。

您可以轻松添加自己的扩展方法:

 public static IEnumerable IndexesWhere(this IEnumerable source, Func predicate) { int index=0; foreach (T element in source) { if (predicate(element)) { yield return index; } index++; } } 

然后使用它:

 string[] s = {"zero", "one", "two", "three", "four", "five"}; var x = s.IndexesWhere(t => t.StartsWith("t")); 

如果您只是使用该示例作为学习LINQ的方法,请忽略此post。


我不清楚LINQ实际上是最好的方法。 下面的代码似乎更有效,因为不需要创建新的匿名类型。 当然,您的示例可能是人为的,并且该技术在不同的上下文中可能更有用,例如在数据结构中可以利用值的索引,但下面的代码是相当直接的,可理解的(没有想到)要求)并且可以说更有效率。

 string[] s = {"zero", "one", "two", "three", "four", "five"}; List matchingIndices = new List(); for (int i = 0; i < s.Length; ++i) { if (s[i].StartWith("t")) { matchingIndices.Add(i); } } 

对我来说似乎很好。 您可以通过将选择更改为以下来保存几个字符:

 .Select((Value, Index) => new {Value, Index}) 

Collection List中还有FindIndex方法,您可以为其创建一个可以从集合中返回索引的delete方法。 您可以参考msdn http://msdn.microsoft.com/en-us/library/x1xzf2ca.aspx中的以下链接。

这个怎么样? 它类似于原始海报,但我首先选择索引,然后构建一个符合标准的集合。

 var x = s.Select((a, i) => i).Where(i => s[i].StartsWith("t")); 

由于列表完全重复两次,因此这比其他一些答案效率低一些。

我和一位同事讨论了这个有趣的问题,起初我认为JonSkeet的解决方案很棒,但我的同事指出了一个问题,即如果函数是IEnumerable的扩展,那么它可以在集合实现它的地方使用。

使用数组,可以肯定地说,使用foreach生成的顺序将被尊重(即foreach将从头到尾迭代),但不一定是其他集合(列表,字典等)的情况,其中foreach不会必然反映“进入秩序”。 然而function就在那里,它可能会产生误导。

最后,我最终得到了类似于tvanfosson的答案,但作为一种扩展方法,对于数组:

 public static int[] GetIndexes(this T[]source, Func predicate) { List matchingIndexes = new List(); for (int i = 0; i < source.Length; ++i) { if (predicate(source[i])) { matchingIndexes.Add(i); } } return matchingIndexes.ToArray(); } 

这里希望List.ToArray会尊重最后一次操作的顺序......