15

使用 Linq;我该怎么做Take的“相反”?

即而不是获取前 n 个元素,例如 in

aCollection.Take(n)

我想得到除了最后 n 个元素之外的所有东西。就像是

aCollection.Leave(n)

(不要问为什么:-)

编辑

我想我可以这样做aCollection.TakeWhile((x, index) => index < aCollection.Count - n)或者以扩展的形式

public static IEnumerable<TSource> Leave<TSource>(this IEnumerable<TSource> source, int n) 
{ 
  return source.TakeWhile((x, index) => index < source.Count() - n); 
}

但是在Linq to SQLNHibernate Linq的情况下,如果生成的 SQL 处理它并生成类似的东西(对于 SQL Server/T-SQL),那就太好了

SELECT TOP(SELECT COUNT(*) -@n FROM ATable) * FROM ATable或者其他一些更聪明的 SQL 实现。

我想没有什么类似的吧?(但编辑实际上不是问题的一部分。)

4

6 回答 6

21
aCollection.Take(aCollection.Count() - n);

编辑:就像评论中出现的一条有趣的信息一样——你可能认为IEnumerable's 扩展方法.Count()很慢,因为它会遍历所有元素。但如果实际对象实现ICollectionor ICollection<T>,它将只使用.Count应该是 O(1) 的属性。所以在这种情况下性能不会受到影响。

IEnumerable.Count() 您可以在 TypeDescriptor.net上查看源代码。

于 2012-04-20T14:05:19.667 回答
11

我很确定没有内置的方法,但这可以通过链接Reverse和轻松完成Skip

aCollection.Reverse().Skip(n).Reverse()
于 2012-04-20T14:04:57.043 回答
5

我不相信有一个内置的功能。

aCollection.Take(aCollection.Count - n)

应该合适;将集合中的项目总数减去 n 应该跳过最后 n 个元素。

于 2012-04-20T14:06:48.647 回答
3

遵循这一理念,并对未实现IEnumerable的情况进行一次枚举,您可以使用这些扩展方法:ICollection

public static IEnumerable<T> Leave<T>(this ICollection<T> src, int drop) => src.Take(src.Count - drop);

public static IEnumerable<T> Leave<T>(this IEnumerable<T> src, int drop) {
    IEnumerable<T> IEnumHelper() {
        using (var esrc = src.GetEnumerator()) {
            var buf = new Queue<T>();
            while (drop-- > 0)
                if (esrc.MoveNext())
                    buf.Enqueue(esrc.Current);
                else
                    break;

            while (esrc.MoveNext()) {
                buf.Enqueue(esrc.Current);
                yield return buf.Dequeue();
            }
        }
    }

    return (src is ICollection<T> csrc) ? csrc.Leave(drop) : IEnumHelper();
}
于 2018-01-11T19:39:04.417 回答
1

这将比具有双重反转的解决方案更有效,因为它只创建一个列表并且只枚举列表一次。

public static class Extensions
{
   static IEnumerable<T> Leave<T>(this IEnumerable<T> items, int numToSkip)
   {
      var list = items.ToList();
      // Assert numToSkip <= list count.
      list.RemoveRange(list.Count - numToSkip, numToSkip);
      return List
   }
}


string alphabet = "abcdefghijklmnopqrstuvwxyz";
var chars = alphabet.Leave(10); // abcdefghijklmnop
于 2012-04-20T14:15:54.490 回答
-2

目前,C#TakeLast(n)定义了一个从字符串末尾获取字符的方法。

见这里:https ://msdn.microsoft.com/en-us/library/hh212114(v=vs.103).aspx

于 2018-05-20T16:30:32.280 回答