如何在C#中获取列表的前N个元素?


384

我想使用Linq查询项目中的公交车时刻表,以便在任何时候都可以获取下5个公交车到达时间。如何将查询限制在前5个结果中?

更一般而言,如何在C#中获取列表的一部分?(在Python中,我将mylist[:5]用来获取前5个元素。)

Answers:


706
var firstFiveItems = myList.Take(5);

或切片:

var secondFiveItems = myList.Skip(5).Take(5);

当然,根据某种顺序获得前五个项目通常很方便:

var firstFiveArrivals = myList.OrderBy(i => i.ArrivalTime).Take(5);

87
如果列表中只有3个项目,是否会引发异常?还是最多需要5个?
bobek '02

87
@bobek:它不会引发异常。如果没有足够的元素,它只是返回它所拥有的。
约书亚·佩奇

1
确切地说,没有任何异常跳过和合并处理解决了我的问题,因为我想进行任何常规收集并每批处理x个项目
JohanLarsson 2015年

应该注意的是,.Take(n)返回一个TakeIterator。它不会返回其中包含n元素的列表(假设有很多元素可用)。使用.ToArray().ToList()在的结果上Take获取具体的数组或列表。
安德鲁·韦伯

69

如果有人感兴趣(即使问题不要求使用该版本),则在C#2中将是:(我根据一些建议对答案进行了编辑)

myList.Sort(CLASS_FOR_COMPARER);
List<string> fiveElements = myList.GetRange(0, 5);

也许还要添加一个匿名谓词?
AlexeyMK

2
List <T> .Sort返回void; 您将需要排序,然后分别使用GetRange。您还可以使用Compare <T>匿名方法来消除对CLASS_FOR_COMPARER的需要。
马克·格雷韦尔

@AlexeyMK-您的意思是一个Compare <T>,而不是谓词(Predicate <T>)-谓词用于过滤数据
Marc Gravell

我相信这个答案即使在现在,十年以及以后的许多C#版本中也很有用。对于您有列表的特定情况。特别是如果您跳过许多项目。例如,您有一个一百万个项目的列表,并且您想要其中的5个项目的一部分进入列表。GetRange确切地知道要去哪里抢它们。我不知道Skip+ Take是否很聪明,或者它是否列举了跳过的项目。而且我不需要知道-我只是使用GetRange(在获得列表时)。只要确保您意识到第二个参数是count(而不是last index)。
制造商史蒂夫(Steve)

有趣的.Take(n)是,您不必担心n序列中的元素是否少于个。问题List<T>.GetRange(0, count)在于您必须担心...。ArgumentException如果没有count物品,您将得到一个提示。
安德鲁·韦伯

5

就像pagination您可以使用以下公式进行服用slice of list or elements

var slice = myList.Skip((pageNumber - 1) * pageSize)
                  .Take(pageSize);

示例1:前五个项目

var pageNumber = 1;
var pageSize = 5;

示例2:后五个项目

var pageNumber = 2;
var pageSize = 5;

示例3:前五个项目

var pageNumber = 3;
var pageSize = 5;

如果通知配方参数pageSize = 5并且pageNumber正在更改,则要更改切片中的项目数,请更改pageSize


1

要更好地采用前5个元素,请使用像这样的表达式:

var firstFiveArrivals = myList.Where([EXPRESSION]).Take(5);

要么

var firstFiveArrivals = myList.Where([EXPRESSION]).Take(5).OrderBy([ORDER EXPR]);

这将比orderBy变体更快,因为LINQ引擎由于执行延迟而不会扫描所有列表,并且不会对所有数组进行排序。

class MyList : IEnumerable<int>
{

    int maxCount = 0;

    public int RequestCount
    {
        get;
        private set;
    }
    public MyList(int maxCount)
    {
        this.maxCount = maxCount;
    }
    public void Reset()
    {
        RequestCount = 0;
    }
    #region IEnumerable<int> Members

    public IEnumerator<int> GetEnumerator()
    {
        int i = 0;
        while (i < maxCount)
        {
            RequestCount++;
            yield return i++;
        }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    #endregion
}
class Program
{
    static void Main(string[] args)
    {
        var list = new MyList(15);
        list.Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 5;

        list.Reset();
        list.OrderBy(q => q).Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 15;

        list.Reset();
        list.Where(q => (q & 1) == 0).Take(5).ToArray();
        Console.WriteLine(list.RequestCount); // 9; (first 5 odd)

        list.Reset();
        list.Where(q => (q & 1) == 0).Take(5).OrderBy(q => q).ToArray();
        Console.WriteLine(list.RequestCount); // 9; (first 5 odd)
    }
}

25
除了您现在只在选择它们之后才订购前5个元素。它可能更快,但也具有不同的语义,这不太可能是人们实际想要实现的。
格雷格·比奇
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.