【问题标题】:Using LINQ, how do I choose items at particular indexes?使用 LINQ,我如何选择特定索引处的项目?
【发布时间】:2010-09-23 08:49:27
【问题描述】:

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

【问题讨论】:

  • 呵呵,看看你得到了多少关注;)
  • 如果 allFoos 是可索引的,那么为什么不使用 IList 而不是 IEnumerable 并避免下面示例中所需的强制转换/转换?
  • @user373743 因为他写道他正在使用 IEnumerable。
  • @user373743:我确实在后台使用List<Foo>。但如果我把问题缩小到这个事实,下面的答案和讨论就不会那么有趣了。 :)
  • @Oskar 是的,我的错我错过了标签。

标签: c# linq ienumerable


【解决方案1】:
var bestFoos = bestFooIndexes.Select(index => allFoos.ElementAt(index));

如果您担心性能并且收藏量很大:

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

【讨论】:

  • @Timwi:我正在写这个建议:)
【解决方案2】:

Elisha 的答案肯定会起作用,但它可能非常低效......这取决于allFoos 的实现方式。如果它是IList&lt;T&gt; 的实现,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]);

【讨论】:

  • 你的意思可能是bestFooIndexes.Select(index =&gt; allFoosList[index]
  • @Henrik:前几天我自己才第一次使用它:)
  • 考虑到以利沙的答案相同,他没有得到公认的答案,这似乎不公平。
  • @Bear:Elisha 的回答很好,但是 Jon 中添加的糖使它变得更好。我没有明确想到 ... 如果它是 IList 的实现,ElementAt 将是高效的... 而且我也喜欢 as IList ? ? allFoos.ToList().
  • @Johann 好的,感谢您的回答。只是为失败者而战;)是的,ICollection 和 IList 的 Linq 优化总体上做得很好。我现在不会再用愚蠢的 cmets 污染你的帖子了 :)
【解决方案3】:

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

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);

【讨论】:

  • 不知道。我喜欢它 - 它与我已经用来选择一个的押韵:var bestFoo = allFoos.ElementAtOrDefault(bestFooIndex)
【解决方案4】:

基于join的另一种解决方案:

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】:

    Jon Skeet / Elisha 的答案是正确的方法。

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

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

    bestFooIndexes 中包含的重复不会在结果中产生重复。此外,结果中的元素将按照它们在allFoos 中的枚举顺序进行排序,而不是按照它们在bestFooIndexes 中出现的顺序。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 2011-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多