所以我们有几个子问题。第一个问题是返回集合中某个元素的 某个投影 的最高值。 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;
}
}
这使我们能够更有效地获取具有最大值的项的索引:
var splitPoint = list.Select((index, number) => new { index, number })
.MaxBy(pair => pair.number)
.index;
接下来,您可以使用跳过(skip)/获取(take)来分割集合:
var firstHalf = list.Take(index);
var secondHalf = list.Skip(index + 1);
你的代码存在一些问题,这里进行了解决。
在查询中,你对每个项都计算了Max
值,而不是计算一次并使用该计算出的值。
然后,你又针对列表中的每个项,将所有项都复制到一个新列表中两次,搜索该列表以尝试找到最大项的位置,然后再尝试找到当前项的位置。你整个过程重复了两次。这意味着你会为每个项四次拷贝整个数组到一个列表中,在集合中为每个项四次搜索最大项的位置,并且通过线性搜索来找到当前项的索引(你可以通过简单地计数来近似计算),对于每个项需要执行两次。随着项目数量的增加,这种方式的效率会变得很低。
这里的代码通过单次遍历集合来查找最大项的索引,然后创建表示每半部分的序列,这些序列除了迭代各项之外几乎没有任何开销。
int item = list.Max()
。 - dee-seeExcept
? - default