从集合中通过索引获取一组项目的最优雅方法是什么?

Bob*_*Bob 10 c#

特定

IList<int> indexes;
ICollection<T> collection;
Run Code Online (Sandbox Code Playgroud)

什么是最优雅的方式来提取所有牛逼收集基础上,提供的索引的索引

例如,如果包含集合

"Brian", "Cleveland", "Joe", "Glenn", "Mort"
Run Code Online (Sandbox Code Playgroud)

并包含索引

1, 3
Run Code Online (Sandbox Code Playgroud)

回报将是

"Cleveland," "Glenn"
Run Code Online (Sandbox Code Playgroud)

编辑:假设索引始终按升序排序.

Eri*_*ert 24

这假设索引序列是非负指数的单调递增序列.策略很简单:对于每个索引,将集合上的枚举器提升到该点并生成元素.

public static IEnumerable<T> GetIndexedItems<T>(this IEnumerable<T> collection, IEnumerable<int> indices)
{
    int currentIndex = -1;
    using (var collectionEnum = collection.GetEnumerator())
    {
        foreach(int index in indices)
        {
            while (collectionEnum.MoveNext()) 
            {
                currentIndex += 1;
                if (currentIndex == index)
                {
                    yield return collectionEnum.Current;
                    break;
                }
            }
        }    
    }
}
Run Code Online (Sandbox Code Playgroud)

此解决方案优于其他解决方案:

  • O(1)在额外存储中 - 这些解决方案中的一些在空间中是O(n)
  • O(n)及时 - 这些解决方案中的一些是时间上的四元数
  • 适用于任何两个序列; 不需要ICollection或IList.
  • 只迭代集合一次; 一些解决方案多次迭代集合(例如,从中构建一个列表).

缺点:

  • 更难读

  • 为什么有人认为"a ++; if(a == b)"在某种程度上比"if(++ a == b)"更难以阅读.我有两个逻辑操作 - 递增副作用和条件转到.将它们组合成一个语句比使它们成为单独的语句更令人困惑.每个陈述都应该有一个任务.不是两个. (5认同)
  • 您的解决方案利用了索引在列表中的事实; 我没有.如果您从索引在可索引列表中并且集合是不可索引的序列的前提开始,那么让您的外部循环遍历集合并使用索引"枚举"列表是有意义的.但是如果你从两个都是不可索引的序列的前提开始,那么从控制流的角度来看,哪个循环"走出去"另一个并不重要. (2认同)
  • 但还有另一个方面.在你的解决方案中,你有一个"元索引" - 代码的读者需要理解indicesIndex是一个INDEX到一个索引列表,这是一个可能混淆的"级别混合".在我的解决方案中,我选择确保currentIndex中的"索引"实际上是集合的索引,而不是集合中索引的索引.这是一个微妙的观点,但我认为这是一个很好的观点. (2认同)

mqp*_*mqp 6

这是一个更快的版本:

IEnumerable<T> ByIndices<T>(ICollection<T> data, IList<int> indices)
{
    int current = 0;
    foreach(var datum in data.Select((x, i) => new { Value = x, Index = i }))
    {
        if(datum.Index == indices[current])
        {
            yield return datum.Value;
            if(++current == indices.Count)
                yield break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)