C# 使用 LINQ 查询获取索引值集合
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/237377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting a collection of index values using a LINQ query
提问by Guy
Is there a better way to do this?
有一个更好的方法吗?
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);
i.e. I'm looking for a more efficient or more elegant way to get the positions of the items matching the criteria.
即我正在寻找一种更有效或更优雅的方式来获取符合条件的项目的位置。
采纳答案by Jon Skeet
You could easily add your own extension method:
您可以轻松添加自己的扩展方法:
public static IEnumerable<int> IndexesWhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int index=0;
foreach (T element in source)
{
if (predicate(element))
{
yield return index;
}
index++;
}
}
Then use it with:
然后使用它:
string[] s = {"zero", "one", "two", "three", "four", "five"};
var x = s.IndexesWhere(t => t.StartsWith("t"));
回答by Mark S. Rasmussen
Seems fine to me. You might save a couple characters by changing the select to:
对我来说似乎很好。您可以通过将选择更改为以下内容来保存几个字符:
.Select((Value, Index) => new {Value, Index})
回答by tvanfosson
If you're just using the example as a way to learn LINQ, ignore this post.
如果您只是将示例用作学习 LINQ 的一种方式,请忽略这篇文章。
It's not clear to me that LINQ is actually the best way to do this. The code below seems like it would be more efficient since no new anonymous type needs to be created. Granted, your example may be contrived and the technique might be more useful in a different context, for example in a data structure where it could take advantage of an index on value, but the code below is reasonably straight-forward, understandable (no thought required) and arguably more efficient.
我不清楚 LINQ 实际上是做到这一点的最佳方式。下面的代码看起来效率更高,因为不需要创建新的匿名类型。当然,您的示例可能是人为的,并且该技术在不同的上下文中可能更有用,例如在可以利用值索引的数据结构中,但下面的代码相当简单,易于理解(没有想到需要)并且可以说更有效。
string[] s = {"zero", "one", "two", "three", "four", "five"};
List<int> matchingIndices = new List<int>();
for (int i = 0; i < s.Length; ++i)
{
if (s[i].StartWith("t"))
{
matchingIndices.Add(i);
}
}
回答by Jon Skeet
There is also FindIndex method in Collection List for which you create a delete method which can return the index from the collection. you can refer to the following link in msdn http://msdn.microsoft.com/en-us/library/x1xzf2ca.aspx.
集合列表中还有 FindIndex 方法,您可以为其创建一个删除方法,该方法可以从集合中返回索引。您可以参考 msdn http://msdn.microsoft.com/en-us/library/x1xzf2ca.aspx 中的以下链接。
回答by Terrence
How about this? It's similar to the original poster's but I first select the indexes and then build a collection which matches the criteria.
这个怎么样?它类似于原始海报,但我首先选择索引,然后构建一个符合条件的集合。
var x = s.Select((a, i) => i).Where(i => s[i].StartsWith("t"));
This is a tad less efficient than some of the other answers as the list is fully iterated over twice.
这比其他一些答案效率稍低,因为列表完全迭代了两次。
回答by MPelletier
I discussed this interesting problem with a colleague and at first I thought JonSkeet's solution was great, but my colleague pointed out one problem, namely that if the function is an extension to IEnumerable<T>
, then it can be used where a collection implements it.
我和一位同事讨论了这个有趣的问题,起初我认为 JonSkeet 的解决方案很棒,但我的同事指出了一个问题,即如果函数是对 的扩展IEnumerable<T>
,那么它可以在集合实现它的地方使用。
With an array, it's safe to say the order produced with foreach
will be respected (i.e. foreach
will iterate from first to last), but it would not necessarily be the case with other collections (List, Dictionary, etc), where foreach
would not reflect necessarily"order of entry". Yet the function is there, and it can be misleading.
随着阵列,它可以安全地说与生成顺序foreach
将受到尊重(即foreach
从第一个到最后一个迭代),但它不一定是与其他收藏品(列表,字典等),那里的情况下,foreach
不能反映一定“入场顺序”。然而,该功能就在那里,它可能会产生误导。
In the end, I ended up with something similar to tvanfosson's answer, but as an extension method, for arrays:
最后,我得到了类似于 tvanfosson 的答案,但作为扩展方法,对于数组:
public static int[] GetIndexes<T>(this T[]source, Func<T, bool> predicate)
{
List<int> matchingIndexes = new List<int>();
for (int i = 0; i < source.Length; ++i)
{
if (predicate(source[i]))
{
matchingIndexes.Add(i);
}
}
return matchingIndexes.ToArray();
}
Here's hoping List.ToArray
will respect the order for the last operation...
希望List.ToArray
能尊重最后一次手术的顺序......