将IEnume拆分为三个部分:"上方","项目","下方",效率高

Joh*_*nes 5 c# linq ienumerable

IEnumerable<int> list = new[] { 1, 2, 7, 3, 11, 5 };
int item = (from x in list where (x == list.Max()) select x).First();
IEnumerable<int> above = from x in list where list.ToList().IndexOf(item) > list.ToList().IndexOf(x) select x;
IEnumerable<int> below = from x in list where list.ToList().IndexOf(item) < list.ToList().IndexOf(x) select x;
Run Code Online (Sandbox Code Playgroud)

我想找到一个元素IEnumerable并将其IEnumerable分成IEnumerable不再包含我找到的元素的s.上面的代码说明了我想要实现的结果,但是我必须将IEnumerable转换为List.

我觉得必须有一种方法可以使用LinQ和IEnumerable来做到这一点.如何才能做到这一点?

Ser*_*rvy 14

所以我们在这里有几个子问题.第一个问题是返回集合中的项目,该集合具有该项目某些投影的最高值. Max仅比较项目本身,或者,如果给定投影,则返回该投影的结果.

public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source
    , Func<TSource, TKey> selector
    , IComparer<TKey> comparer = null)
{
    if (comparer == null)
    {
        comparer = Comparer<TKey>.Default;
    }
    using (IEnumerator<TSource> iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            throw new ArgumentException("Source was empty");
        }

        TSource maxItem = iterator.Current;
        TKey maxValue = selector(maxItem);

        while (iterator.MoveNext())
        {
            TKey nextValue = selector(iterator.Current);
            if (comparer.Compare(nextValue, maxValue) > 0)
            {
                maxValue = nextValue;
                maxItem = iterator.Current;
            }
        }
        return maxItem;
    }
}
Run Code Online (Sandbox Code Playgroud)

这使我们能够更有效地获取具有最大值的项目的索引:

var splitPoint = list.Select((index, number) => new { index, number })
    .MaxBy(pair => pair.number)
    .index;
Run Code Online (Sandbox Code Playgroud)

在拆分集合旁边,您只需使用skip/take:

var firstHalf = list.Take(index);
var secondHalf = list.Skip(index + 1);
Run Code Online (Sandbox Code Playgroud)

您在此处解决的代码存在许多不同的问题.

您计算查询中每个项目Max值,而不是计算一次并使用该计算值.item

然后,对于列表中的每个项目,然后将所有项目复制到新列表,两次,搜索该列表以尝试查找最大项目的位置,然后尝试查找当前项目的位置.然后你做了两次整件事.这意味着您将每个项目的整个数组复制到列表中四次,在集合中每个项目搜索最多项目的位置四次,并线性搜索列表以查找当前项目的索引(某些内容)你可以在几乎没有时间计算每个项目只计算两次.随着物品数量的增加,这将很难扩展......

这里的代码在集合的单个过程中找到最大项的索引,然后创建表示每一半的序列,除了简单地遍历这些项之外,每个序列几乎没有任何开销.

  • "Take()"和"Skip()"的+1.虽然创建扩展可能看起来有点过分.我会使用Filipe的答案并使用`Take()`和`Skip()`. (2认同)