Как получить первые 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.