Linq:Take的“对立面”?

时间:2012-04-20 14:02:40

标签: c# linq

使用Linq;我该怎么做Take的“对立面”?

即。而不是像

中那样获得前n个元素
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 SQL NHibernate Linq 的情况下,如果生成的SQL处理它并生成类似的内容(对于SQL Server / T-SQL)

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

我想没有什么比这更好的了吗? (但编辑实际上不是问题的一部分。)

6 个答案:

答案 0 :(得分:21)

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

编辑:正如评论中提到的一条有趣信息一样 - 您可能认为IEnumerable的扩展方法.Count()速度很慢,因为它将迭代所有元素。但是如果实际对象实现ICollectionICollection<T>,它将只使用应该为O(1)的.Count属性。因此,在这种情况下,性能不会受到影响。

您可以看到IEnumerable.Count() at TypeDescriptor.net的源代码。

答案 1 :(得分:11)

我很确定没有内置的方法,但可以通过链接ReverseSkip轻松完成:

aCollection.Reverse().Skip(n).Reverse()

答案 2 :(得分:5)

我不相信这有内置功能。<​​/ p>

aCollection.Take(aCollection.Count - n)

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

答案 3 :(得分:3)

保持IEnumerable philosphy,并在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();
}

答案 4 :(得分: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

答案 5 :(得分:-2)

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

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