C# 将IEnumerable分为三部分:“;在“上面”&引用;项目“&引用;以下是「;有效率 IEnumerable list=new[]{1,2,7,3,11,5}; int item=(从列表中的x开始,其中(x==list.Max())选择x); 上面的IEnumerable=列表中的x,其中list.ToList().IndexOf(item)>list.ToList().IndexOf(x)选择x; IEnumerable below=列表中的x,其中list.ToList().IndexOf(item)索引索引>索引值);

C# 将IEnumerable分为三部分:“;在“上面”&引用;项目“&引用;以下是「;有效率 IEnumerable list=new[]{1,2,7,3,11,5}; int item=(从列表中的x开始,其中(x==list.Max())选择x); 上面的IEnumerable=列表中的x,其中list.ToList().IndexOf(item)>list.ToList().IndexOf(x)选择x; IEnumerable below=列表中的x,其中list.ToList().IndexOf(item)索引索引>索引值);,c#,linq,ienumerable,C#,Linq,Ienumerable,我想在IEnumerable中找到一个元素,并将IEnumerable拆分为IEnumerable中不再包含我找到的元素。上面的代码说明了我想要实现的结果,但是我必须将IEnumerable转换为列表 我觉得必须有一种方法来做到这一点,只使用LinQ和IEnumerable。 如何做到这一点?尝试使用可使用索引的扩展方法。查看下面的示例和注释 IEnumerable<int> list = new[] { 1, 2, 7, 3, 11, 5 }; int item = (from x

我想在
IEnumerable
中找到一个元素,并将
IEnumerable
拆分为
IEnumerable
中不再包含我找到的元素。上面的代码说明了我想要实现的结果,但是我必须将IEnumerable转换为列表

我觉得必须有一种方法来做到这一点,只使用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;
//定义列表
IEnumerable list=new[]{1,2,7,3,11,5};
//定义一些值(样本中的最大值)
int value=list.Max();
//获取所需值的索引
int indexValue=list.ToList().IndexOf(值);
//查找收藏
上面的IEnumerable=列表。其中((值,索引)=>索引<索引值);
下面的IEnumerable=列表。其中((值,索引)=>索引>索引值);

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

// define the list
IEnumerable<int> list = new[] { 1, 2, 7, 3, 11, 5 };

// define some value (max in your sample)
int value = list.Max();

// get the index of the value you want
int indexValue = list.ToList().IndexOf(value);

// find collections
IEnumerable<int> above = list.Where((value, index) => index < indexValue);
IEnumerable<int> below = list.Where((value, index) => index > indexValue);
在拆分集合的旁边,您只需使用skip/take:

var splitPoint = list.Select((index, number) => new { index, number })
    .MaxBy(pair => pair.number)
    .index;
您的代码中有许多不同的问题需要在这里解决

您可以计算查询中每个项目的
Max
值以获得
item
,而不是只计算一次并使用该计算值

然后,针对列表中的每个项目,将所有项目复制到新列表中,两次搜索该列表以尝试查找最大项目的位置,然后尝试查找当前项目的位置。然后你把这整件事做两次。这意味着您要为每个项目将整个数组复制到一个列表中四次,为集合中的每个项目搜索最大项目的位置四次,然后在列表中线性搜索,为每个项目查找当前项目的索引两次(您可以在几乎不需要时间的情况下通过计数计算)。随着项目数量的增加,这将很难扩展


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

首先,您需要找到max元素的(第一个)索引。作为Servy答案的一种变体,可以使用
Select
Aggregate
来完成此操作。然后枚举索引前后的元素:

var firstHalf = list.Take(index);
var secondHalf = list.Skip(index + 1);
var indexOfMax=list
.选择((值,索引)=>新的KeyValuePair(索引,值))
.Aggregate(新的KeyValuePair(-1,-1),(最小值,当前值)=>
{
如果(最小键==-1 | |当前值>最小值)
返回电流;
返回最小值;
}).钥匙;
变量开始=list.Take(indexOfMax);
var end=list.Skip(indexOfMax+1);

首先,您需要保证您的
IEnumerable
对象包含特定顺序的项。这可以通过使用
IOrderedEnumerable
而不是简单无序的
IEnumerable
来实现,或者使用可以通过索引引用元素的
IList
来实现


当你弄明白了这一点后,分裂变得非常简单:按索引或顺序遍历元素,并将它们添加到上面的
IList
,直到找到你的元素。跳过该元素,然后继续遍历这些元素,同时将它们添加到下面的
IList

首先,您可以简单地使用
int item=list.Max()
,听起来你想使用?@默认值我在上读到,除了-似乎它从列表中删除了一项-我看不出如何在拆分点将结果拆分为两个IEnumerable。@Mrchief:不。OP正在查找每一项的索引。这将索引作为参数提供,而且效率更高。编译器无论如何都会将其内联,这样您就不会每次都产生查找成本。@Mrchief不,不会。它不知道集合没有更改。@Mrchief编译器不知道(或者至少不能证明它),所以它不能延迟操作。@Mrchief哦,当我们在做的时候,内联并不是你认为它的意思。内联仅仅意味着获取一个短方法的主体,并使用该代码代替对该方法的调用。这避免了为非常简短和简单的方法创建堆栈框架。您似乎用它来表示缓存方法的结果并返回缓存的结果,而不是重新计算它。那就是回忆录。内联确实经常发生(尽管这个方法很复杂,我怀疑它在这里不会发生),但是编译器/运行时几乎没有记忆。
Take()
Skip()
的+1。尽管创建一个扩展似乎有些过分。相反,我会使用Filipe的答案,并使用
Take()
Skip()
@rcdmk。这增加了复杂性,以换取具有广泛应用的有用的通用方法,并且还消除了将整个集合具体化为一个列表,然后迭代该列表以再次查找您之前已经找到的项的需要。如果集合恰好足够小,这不是一个问题,那么这很好,但这个问题的关键是选择
var firstHalf = list.Take(index);
var secondHalf = list.Skip(index + 1);
        var indexOfMax = list
            .Select((value, index) => new KeyValuePair<int, int>(index, value))
            .Aggregate(new KeyValuePair<int, int>(-1, -1), (min, cur) => 
                {
                    if (min.Key == -1 || cur.Value > min.Value)
                        return cur;
                    return min;
                }).Key;

        var beginning = list.Take(indexOfMax);
        var end = list.Skip(indexOfMax + 1);