使用LINQ删除最后一项

Kei*_*Kei 34 c# linq

可能重复:
如何使用LINQ获取序列中除最后一个元素之外的所有元素?

看起来像是一个简单的LINQ任务(可能是它),但我无法弄清楚如何使用LINQ删除最后一项序列.使用Take并传递序列的长度 - 1当然可以正常工作.但是,在单行代码中链接多个LINQ时,这种方法似乎非常不方便.

IEnumerable<T> someList ....

// this works fine
var result = someList.Take(someList.Count() - 1);


// but what if I'm chaining LINQ ?
var result = someList.Where(...).DropLast().Select(...)......;

// Will I have to break this up?
var temp = someList.Where(...);
var result = temp.Take(temp.Count() - 1).Select(...)........;
Run Code Online (Sandbox Code Playgroud)

在Python中,我可以做seq [0:-1].我尝试将-1传递给Take方法,但它似乎没有做我需要的东西.

sta*_*ica 62

对于.NET Core 2+和.NET Standard 2.1(计划),您可以使用.SkipLast(1).

对于其他平台,您可以编写自己的LINQ查询操作符(也就是一个扩展方法IEnumerable<T>),例如:

static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
{
    using (var e = source.GetEnumerator())
    {
        if (e.MoveNext())
        {
            for (var value = e.Current; e.MoveNext(); value = e.Current)
            {
                yield return value;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

与其他方法不同xs.Take(xs.Count() - 1),上述方法仅处理序列一次.

  • 遗憾的是,这个答案没有出现在[标记的欺骗]中(http://stackoverflow.com/questions/1779129/how-to-take-all-but-the-last-element-in-a-sequence-使用-LINQ).它比那里接受的答案更整洁. (4认同)

Sae*_*iri 23

someList.Reverse().Skip(1).Reverse()
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这也将整个序列存储在内存中 - 两次.如果序列非常长,则可能是*很多*的内存.是的,这种技术在时间上是O(n),但它在空间中也是O(n),在空间中它可以是O(1). (13认同)
  • @LukeH,它是O(n),它是OP想要的一行答案. (2认同)
  • 哦,为什么我没有想到这个:)这是一个聪明而简单的方法,可以开箱即用.不太清楚性能意味着什么,但如果我只需要快速而肮脏的方式来完成它,这是一个很好的方法. (2认同)
  • 好吧,为了论证起见,我们假设该序列是 O(n) 空间。那么您是否有理由再次消耗**两倍的空间**?那东西可能很大。 (2认同)

Jam*_*iec 13

您可以使用扩展方法轻松完成此操作,可以使用您已经找到的表单,也可以使用Take和的组合Count

public static IEnumerable<T> DropLast<T>(this IEnumerable<T> enumerable)
{
  return enumerable.Take(enumerable.Count()-1);
}
Run Code Online (Sandbox Code Playgroud)

  • `Except`方法不适用于此,因为它还会从源序列中删除任何重复项.如果源是"{1,2,3,4,5,4,3,2,1}"那么OP会期望结果为"{1,2,3,4,5,4,3, 2}`; 使用你的第二个例子(假设你修复了bug)会给`{2,3,4,5}`. (11认同)
  • 这也有效:xs.TakeWhile((x,i)=> i <xs.Count() - 1) (2认同)