2015-09-16 2 views
2

Я пытаюсь сравнить два списка. Вот метод расширения Я пытаюсь использовать:Самый эффективный способ сравнить два списка <T>

public static bool EqualsAll<T>(this IList<T> a, IList<T> b) 
{ 
    if (a == null || b == null) 
     return (a == null && b == null); 

    if (a.Count != b.Count) 
     return false; 

    EqualityComparer<T> comparer = EqualityComparer<T>.Default; 

    for (int i = 0; i < a.Count; i++) 
    { 
     if (!comparer.Equals(a[i], b[i])) 
      return false; 
    } 

    return true; 
} 

Я уже задавал этот вопрос here. Но мне нужно больше информации об этом. ответчик сказал, что лучше использовать SequenceEqual вместо for.

Теперь мой вопрос в том, какой из двух подходов является наиболее эффективным способом сравнения двух List<T>?

+14

[Horses ...] (http://ericlippert.com/2012/12/17/performance-rant/) –

+3

Настоятельно рекомендую вам проверить первое условие и как вы оцениваете возврат. Это эффективно синтаксически. – MPelletier

+1

@AlexeiLevenkov Возможно, мне следовало бы изменить название. –

ответ

6

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

Что касается использования, перейдите с SequenceEqual - он встроен в каркас, другие программисты уже знают его функциональность, и самое главное, нет необходимости изобретать велосипед.

+0

Этот ответ хорош, поскольку он фокусируется на практическом воздействии (вероятной) незначительной микрооптимизации. – poke

+0

@poke еще, он не отвечает. В нем говорится: «Ваш вопрос не имеет значения». Это невозможно. – usr

+0

@usr Нет, вопрос в высшей степени субъективен. Эффективность - это не просто «скорость исполнения» (не говоря уже о том, что это также очень зависит от контекста использования).Это также много «для того, что мне нужно, чтобы сделать что-то быстрее». – poke

3

Как IList<T> орудия IEnumerable<T>, а документированные here, я считаю, что

a.SequenceEqual(b) 

является разумным способом сделать сравнение с методом exentsion документируется here.

+4

_ «Что быстрее?» _ - _ «Вы можете использовать этот» _. – CodeCaster

+2

Я ничего не могу поделать; Я должен подтвердить ваш комментарий. – Codor

3

Самый эффективный способ сравнить с объектами List<T> - это не пройти через интерфейсную обработку, используя IList. Вместо этого, специализируйте тип до List<T>. Аргументы должны быть List<T>.

Это экономит много косвенных вызовов. Это явно быстрее, чем IEnumerable на основе SequenceEquals, в то время как требуется два косвенных вызова на элемент.

Кроме того, вам необходимо кэшировать счетчик.

Было бы лучше, если бы List<T> имел встроенный метод или реализовал определенный интерфейс или разрешил доступ к его внутреннему буферу. Но ничто из этого не доступно.

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

Есть также вещи, которые вы можете сделать, чтобы избежать стоимости сравнения. Это действительно зависит от того, насколько важна эта проблема. Вы можете в полной мере оптимизировать это.

+0

Интересно, вы говорите, что абстрактный 'IList ' стандартный ** интерфейс ** посвящен конкретному «списку ' ** class **. Если бы это было правдой, это было бы довольно странное решение команды BCL. Также ОП не сказал, что он фактически передает «Список ' s. Как насчет того, чтобы 'T []' например. –

+0

@ IvanStoev он говорит это в заголовке и в тексте, что это список . – usr

+0

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

Смежные вопросы