Une idée sur la façon de vérifier si cette liste est un sous-ensemble d'une autre?
Plus précisément, j'ai
List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };
Comment vérifier que t2 est un sous-ensemble de t1, en utilisant LINQ?
Réponses:
la source
Utilisez HashSet au lieu de List si vous travaillez avec des ensembles. Ensuite, vous pouvez simplement utiliser IsSubsetOf ()
Désolé qu'il n'utilise pas LINQ. :-(
Si vous avez besoin d'utiliser des listes, la solution de @ Jared fonctionne avec l'avertissement que vous devrez supprimer tous les éléments répétés qui existent.
la source
Si vous effectuez des tests unitaires, vous pouvez également utiliser la méthode CollectionAssert.IsSubsetOf :
Dans le cas ci-dessus, cela signifierait:
la source
C'est une solution nettement plus efficace que les autres publiées ici, en particulier la meilleure solution:
Si vous pouvez trouver un seul élément dans t2 qui n'est pas dans t1, alors vous savez que t2 n'est pas un sous-ensemble de t1. L'avantage de cette méthode est qu'elle se fait entièrement en place, sans allouer d'espace supplémentaire, contrairement aux solutions utilisant .Except ou .Intersect. De plus, cette solution est capable de s'interrompre dès qu'elle trouve un élément unique qui viole la condition du sous-ensemble, tandis que les autres continuent la recherche. Vous trouverez ci-dessous la forme longue optimale de la solution, qui n'est que légèrement plus rapide dans mes tests que la solution abrégée ci-dessus.
J'ai fait une analyse rudimentaire des performances de toutes les solutions, et les résultats sont drastiques. Ces deux solutions sont environ 100 fois plus rapides que les solutions .Except () et .Intersect () et n'utilisent aucune mémoire supplémentaire.
la source
!t2.Except(t1).Any()
faisons. Linq travaille d'avant en arrière.Any()
demande à unIEnumerable
s'il y a au moins un élément. Dans ce scénariot2.Except(t1)
n'émet que le premier élémentt2
dont n'est past1
. Si le premier élément det2
n'est past1
dedans, il se termine le plus rapidement, si tous les éléments de yt2
sont,t1
il s'exécute le plus longtemps.t1={1,2,3,...9999}
ett2={9999,9998,99997...9000}
, vous obtenez les mesures suivantes:!t2.Except(t1).Any(): 1ms -> t2.All(e => t1.Contains(e)): 702ms
. Et c'est pire avec la portée.t2.Except (t1)
renvoie unIEnumerable
pas unCollection
. Il n'émet tous les éléments possibles que si vous le parcourez complètement, par exemple parToArray ()
ouToList ()
ou utilisezforeach
sans pénétrer à l'intérieur. Recherchez l' exécution différée de linq pour en savoir plus sur ce concept.t2={1,2,3,4,5,6,7,8}
t1={2,4,6,8}
t2.Except(t1)
=> premier élément de t2 = 1 => la différence de 1 à t1 est 1 (vérifiée par rapport à {2,4,6,8}) =>Except()
émet le premier élément 1 =>Any()
obtient un élément =>Any()
aboutit à vrai => aucune vérification supplémentaire des éléments de t2.@ La solution de Cameron comme méthode d'extension:
Usage:
(Ceci est similaire, mais pas tout à fait le même que celui publié sur le blog de @ Michael)
la source
En me basant sur les réponses de @Cameron et @Neil, j'ai écrit une méthode d'extension qui utilise la même terminologie que la classe Enumerable.
la source
par exemple:
la source
Essaye ça
L'idée ici est que Intersect ne renverra que les valeurs qui se trouvent dans les deux tableaux. À ce stade, si la longueur de l'ensemble résultant est la même que celle de l'ensemble d'origine, alors tous les éléments de «set» sont également en «check» et donc «set» est un sous-ensemble de «toCheck»
Remarque: ma solution ne fonctionne pas si "set" a des doublons. Je ne le change pas parce que je ne veux pas voler les votes des autres.
Indice: j'ai voté pour la réponse de Cameron.
la source