C# 如何使用Lambda从列表中获取最后x条记录

C# 如何使用Lambda从列表中获取最后x条记录,c#,lambda,c#-4.0,C#,Lambda,C# 4.0,我有一个字符串列表,其中我删除了每个重复项,现在我想对它进行更多的过滤,以获得最后5条记录。我该怎么做 到目前为止我得到了什么 List<string> query = otherlist.Distinct().Select(a => a).ToList(); List query=otherlist.Distinct().Select(a=>a.ToList(); 这个怎么样 var lastFive = list.Reverse().Take(5).Reverse();

我有一个字符串列表,其中我删除了每个重复项,现在我想对它进行更多的过滤,以获得最后5条记录。我该怎么做

到目前为止我得到了什么

 List<string> query = otherlist.Distinct().Select(a => a).ToList();
List query=otherlist.Distinct().Select(a=>a.ToList();
这个怎么样

var lastFive = list.Reverse().Take(5).Reverse();
编辑:事情是这样的-

var lastFiveDistinct = otherlist.Distinct()
                                .Reverse()
                                .Take(5)
                                .Reverse()
                                .ToList();

还要注意的是,如果最后有一个
ToList()
调用,则不应调用它
query
,因为这样它就不再是查询了,而是经过计算并变成了一个列表。如果只需要对其进行迭代,可以省略
ToList()
调用,并将其保留为
IEnumerable

您不需要
。选择(a=>a)
。那是多余的

你可以跳过剩下的5条记录,如

List<string> query = otherlist.Distinct().ToList();
List<string> lastFive = query.Skip(query.Count-5).ToList();
List query=otherlist.Distinct().ToList();
List lastFive=query.Skip(query.Count-5.ToList();
编辑:


我错过了数据列表。对于IEnumerable

编辑来说,这种方法更适合于非列表输入,现在处理
IEnumerable
并检查这是否是一个
IList
;如果没有,它将通过
ToList()
对数据进行缓冲,这有助于确保我们只读取一次数据(而不是
.Count()
.Skip()
,这可能会多次读取数据)

由于这是一个列表,我倾向于编写一个扩展方法,充分利用它:

    public static IEnumerable<T> TakeLast<T>(
           this IEnumerable<T> source, int count)
    {
        IList<T> list = (source as IList<T>) ?? source.ToList();
        count = Math.Min(count, list.Count);
        for (int i = list.Count - count; i < list.Count; i++)
        {
            yield return list[i];
        }
    }
公共静态IEnumerable TakeLast(
此IEnumerable源(整数计数)
{
IList list=(源代码为IList)??source.ToList();
count=Math.Min(count,list.count);
for(int i=list.Count-Count;i
为什么
选择(a=>a)
?它什么都没做……我的“傻瓜”就是把最后的x记录过滤掉。我敢说,计数元素然后使用Skip and Take会更便宜。反转IEnumerable并不便宜。无论哪种方式,它的渐进复杂性都是一样的,但你是对的,skip/take可能更快。事实上,我将修改我之前的陈述-我认为不会有明显的性能差异。请看我对Jens答案的评论。Skip()的性能明显优于Reverse()然后Take()。@Danny:没有你想象的那么好:
ToList()
调用将与我的第一个
Reverse()
(遍历整个列表一次)一样昂贵,在
Take(5)
之后,它只是在反转五个元素,这是微不足道的。而且,我的方式不会创建中间列表。@tzaman-“我的方式不会创建中间列表”-是的,它会;事实上,其中有两个。您认为
Reverse
是如何操作的?(严格来说,它创建了一个
T[]
数组,由
Buffer
-提供,但区别相同)@Marc-huh。当然我真傻。尽管如此,我刚才做的一点计时似乎表明我的解决方案比这个(或你的)运行得更快。看一看?绝对地如果您知道它是一个列表,那么这是一个简单且容易实现的最有效的方法;
ToList()
只需在末尾执行一次。
    public static IEnumerable<T> TakeLast<T>(
           this IEnumerable<T> source, int count)
    {
        IList<T> list = (source as IList<T>) ?? source.ToList();
        count = Math.Min(count, list.Count);
        for (int i = list.Count - count; i < list.Count; i++)
        {
            yield return list[i];
        }
    }