使用LINQ,如何在特定索引中选择项目?

时间:2010-09-23 08:49:27

标签: c# linq ienumerable

如果我有IEnumerable<Foo> allFoosIEnumerable<Int32> bestFooIndexes,如何在指定的索引处获取包含IEnumerable<Foo> bestFoos Foo条目的新allFoos bestFooIndexes

6 个答案:

答案 0 :(得分:12)

var bestFoos = bestFooIndexes.Select(index => allFoos.ElementAt(index));

如果你担心表演并且收藏很大,那么:

List<Foo> allFoosList = allFoos.ToList();
var bestFoos = bestFooIndexes.Select(index => allFoosList[index]);

答案 1 :(得分:11)

Elisha的答案肯定会有效,但可能效率非常低......这取决于allFoos的实施情况。如果它是IList<T>的实现,ElementAt将是有效的 - 但如果它实际上是(例如)LINQ to Objects查询的结果,那么将为每个索引重新运行查询。所以可能更有效率地写作:

var allFoosList = allFoos.ToList();
// Given that we *know* allFoosList is a list, we can just use the indexer
// rather than getting ElementAt to perform the optimization on each iteration
var bestFoos = bestFooIndexes.Select(index => allFoosList[index]);

当你需要的时候,你可以这样做:

IList<Foo> allFoosList = allFoos as IList<Foo> ?? allFoos.ToList();
var bestFoos = bestFooIndexes.Select(index => allFoosList[index]);

答案 2 :(得分:2)

你可以像这样制作一个扩展方法:

public IEnumerable<T> ElementsAt(this IEnumerable<T> list, IEnumerable<int> indexes)
{
     foreach(var index in indexes)
     {
           yield return list.ElementAt(index);
     }

}

然后你可以这样做

var bestFoos = allFoos.ElementsAt(bestFooIndexes);

答案 3 :(得分:1)

Jon Skeet / Elisha的答案是要走的路。

这是一个稍微不同的解决方案,很可能效率不高:

var bestFooIndices = new HashSet<int>(bestFooIndexes);
var bestFoos = allFoos.Where((foo, index) => bestFooIndices.Contains(index));

bestFooIndexes中包含的重复不会在结果中产生重复。此外,结果中的元素将按其allFoos中的枚举顺序排序,而不是按bestFooIndexes中的顺序排序。

答案 4 :(得分:1)

另一种基于联接的解决方案:

var bestFoos = from entry in allFoos
                               .Select((a, i) = new {Index = i, Element = a})
           join index in bestFooIndexed on entry.Index equals index
           select entry.Element;

答案 5 :(得分:0)

var bestFoosFromAllFoos = allFoos.Where((s)=&gt; bestFoos.Contains(s));