Подтвердить что ты не робот

Общий список FindAll() против foreach

Я просматриваю общий список, чтобы найти элементы на основе определенного параметра.

В целом, какая была бы лучшая и быстрая реализация?
1. Прокручивание каждого элемента в списке и сохранение каждого совпадения в новом списке и возвращение этого

foreach(string s in list)
{ 
    if(s == "match")
    {
       newList.Add(s);
    }
} 

return newList;

Или
2. Используя метод FindAll и передав ему делегат.

newList = list.FindAll(delegate(string s){return s == "match";});

Разве они оба не работают в ~ O (N)? Что было бы лучше всего здесь?

С уважением, Джонатан

4b9b3361

Ответ 1

Вы должны определенно использовать метод FindAll или эквивалентный метод LINQ. Кроме того, рассмотрите возможность использования более сжатой лямбды вместо вашего делегата, если вы можете (требуется С# 3.0):

var list = new List<string>();
var newList = list.FindAll(s => s.Equals("match"));

Ответ 2

В этом случае я бы использовал метод FindAll, поскольку он более краток и IMO имеет более удобную читаемость.

Вы правы, что они в значительной степени будут выполнять в O (N) время, хотя foreach statement должен быть немного быстрее, поскольку ему не нужно выполнять вызов делегата (делегаты несут небольшие накладные расходы, а не напрямую вызывающие методы).

Я должен подчеркнуть, насколько незначительна эта разница, она более чем вероятно никогда не изменит ситуацию, если вы не делаете огромное количество операций в массивном списке.

Как всегда, проверьте, где узкие места и действуют надлежащим образом.

Ответ 3

Джонатан

Хороший ответ вы можете найти в главе 5 (соображения производительности) Linq To Action.

Они измеряют a для каждого поиска, который выполняется около 50 раз, и который встречается с foreach = 68 мс за цикл /List.FindAll = 62ms за цикл. На самом деле, вероятно, вам будет интересно только создать тест и убедиться в этом.

Ответ 4

List.FindAll - это O (n) и будет искать весь список.

Если вы хотите запустить свой собственный итератор с foreach, я бы рекомендовал использовать оператор yield и, если возможно, возвратил IEnumerable. Таким образом, если вам в итоге понадобится только один элемент вашей коллекции, он будет быстрее (поскольку вы можете остановить своего абонента без исчерпания всей коллекции).

В противном случае, придерживайтесь интерфейса BCL.

Ответ 5

Любая перформанса будет крайне незначительной. Я бы предложил FindAll для ясности или, если возможно, перечислить. Где. Я предпочитаю использовать методы Enumerable, потому что он обеспечивает большую гибкость при рефакторинге кода (вы не принимаете зависимость от List<T>).

Ответ 6

Да, обе реализации - O (n). Они должны посмотреть на каждый элемент в списке, чтобы найти все совпадения. С точки зрения удобочитаемости я также предпочел бы FindAll. Для соображений производительности смотрите LINQ в действии (Ch 5.3). Если вы используете С# 3.0, вы также можете применить выражение лямбда. Но это только глазурь на торте:

var newList = aList.FindAll(s => s == "match");

Ответ 7

Im с Lambdas

List<String> newList = list.FindAll(s => s.Equals("match"));

Ответ 8

Если команда С# не улучшила производительность для LINQ и FindAll, следующая статья, похоже, предполагает, что for и foreach будут превосходить LINQ и FindAll при перечислении объектов: LINQ для производительности объектов.

Этот артикул был датирован март 2009 года, как раз перед этим сообщением, которое первоначально было задано.