Любая идея о том, как проверить, является ли этот список подмножеством другого?
В частности, у меня есть
List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };
Как проверить, что t2 является подмножеством t1, используя LINQ?
Ответы:
источник
Используйте HashSet вместо List, если работаете с наборами. Тогда вы можете просто использовать IsSubsetOf ()
Извините, что он не использует LINQ. :-(
Если вам нужно использовать списки, то решение @ Jared работает с предупреждением о том, что вам нужно будет удалить все повторяющиеся элементы, которые существуют.
источник
Если вы проводите модульное тестирование, вы также можете использовать метод CollectionAssert.IsSubsetOf :
В приведенном выше случае это будет означать:
источник
Это значительно более эффективное решение, чем другие, размещенные здесь, особенно топовое решение:
Если вы можете найти один элемент в t2, которого нет в t1, то вы знаете, что t2 не является подмножеством t1. Преимущество этого метода в том, что он выполняется на месте, без выделения дополнительного пространства, в отличие от решений, использующих .Except или .Intersect. Кроме того, это решение может сломаться, как только оно найдет один элемент, который нарушает условие подмножества, в то время как другие продолжают поиск. Ниже приведена оптимальная длинная форма решения, которая в моих тестах лишь незначительно быстрее, чем приведенное выше сокращенное решение.
Я сделал некоторый элементарный анализ производительности всех решений, и результаты были радикальными. Эти два решения примерно в 100 раз быстрее, чем решения .Except () и .Intersect (), и не используют дополнительную память.
источник
!t2.Except(t1).Any()
делает. Линк работает вперед и назад.Any()
спрашивает, естьIEnumerable
ли хотя бы один элемент. В этом сценарииt2.Except(t1)
испускается только первый элемент,t2
которого нет вt1
. Если первый элементt2
не находится вt1
нем, он заканчивается быстрее всего, если все элементыt2
находятся вt1
нем, он работает дольше всего.t1={1,2,3,...9999}
иt2={9999,9998,99997...9000}
, вы получаете следующие измерения:!t2.Except(t1).Any(): 1ms -> t2.All(e => t1.Contains(e)): 702ms
. И чем хуже диапазон, тем хуже.t2.Except (t1)
возвращаетсяIEnumerable
не собойCollection
. Он испускает все возможные элементы, только если вы перебираете его полностью, например, с помощьюToArray ()
илиToList ()
или используетеforeach
без разрыва внутри. Найдите отложенное выполнение linq, чтобы узнать больше об этой концепции.t2={1,2,3,4,5,6,7,8}
t1={2,4,6,8}
t2.Except(t1)
=> первый элемент t2 = 1 => разница от 1 до t1 равна 1 (проверено по {2,4,6,8}) =>Except()
испускает первый элемент 1 =>Any()
получает элемент =>Any()
приводит к true => нет дальнейшей проверки элементов в t2.Решение Кэмерона в качестве метода расширения:
Использование:
(Это похоже, но не совсем то, что опубликовано в блоге @ Michael)
источник
Основываясь на ответах @Cameron и @Neil, я написал метод расширения, использующий ту же терминологию, что и класс Enumerable.
источник
например:
источник
Попробуй это
Идея в том, что Intersect будет возвращать только те значения, которые есть в обоих массивах. В этот момент, если длина результирующего набора совпадает с исходным набором, тогда все элементы в «наборе» также находятся в «проверке», и, следовательно, «набор» является подмножеством «toCheck»
Примечание. Мое решение не работает, если в «множестве» есть дубликаты. Я не изменяю это, потому что я не хочу красть голоса других людей.
Подсказка: я голосовал за ответ Кэмерон.
источник