Как получить первые N элементов списка в C #?


384

Я хотел бы использовать Linq для запроса расписания автобусов в моем проекте, чтобы в любое время я мог получить следующие 5 раз прибытия автобусов. Как я могу ограничить свой запрос первыми 5 результатами?

В целом, как я могу взять часть списка в C #? (В Python я бы использовал, mylist[:5]чтобы получить первые 5 элементов.)

Ответы:


709
var firstFiveItems = myList.Take(5);

Или нарезать:

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

И, конечно же, часто бывает удобно получить первые пять предметов по какому-то порядку:

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

87
Выдает ли исключение, если в списке только 3 элемента? Или это займет столько, сколько есть до 5?
— Бобек

87
@bobek: это не исключение. Он просто возвращает то, что имеет, если не хватает элементов.
— Джошуа Печ

1
точно, без исключений «Пропустить и взять» в совокупности решил мою проблему, так как я хотел взять любую общую коллекцию и обработать х элементов в пакете
— JohanLarsson

Следует отметить, что .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 отдельно. Вы также можете использовать анонимный метод Comparison <T>, чтобы устранить необходимость в CLASS_FOR_COMPARER.
— Марк Гравелл

@AlexeyMK - вы имеете в виду Сравнение <T>, а не предикат (Predicate <T>) - предикат используется для фильтрации данных
— Марк Гравелл

Я считаю, что этот ответ полезен даже сейчас, спустя 10 лет и многие версии C #. Для конкретного случая, когда у вас есть список. Особенно, если вы пропускаете много предметов. Например, у вас есть список из одного миллиона предметов, и вы хотите, чтобы часть из 5 из них находилась далеко в списке. GetRange точно знает, куда их отправлять. Я не знаю, насколько «умный» Skip+ Takeили он перечисляет пропущенные элементы. И мне не нужно знать - я просто использую GetRange (когда предоставляется список). Просто убедитесь, что вы понимаете, что вторым параметром является число (а не последний индекс ).
— ToolmakerSteve

Приятно то, .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 элементов после того, как выбрали их. Это может быть быстрее, но также имеет другую семантику, которая с меньшей вероятностью будет тем, чего люди на самом деле хотят достичь.
— Грег Бич
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.