Je dois vérifier si une liste est un sous-ensemble d'une autre - un retour booléen est tout ce que je recherche.
Tester l'égalité sur la plus petite liste après une intersection est-il le moyen le plus rapide de le faire? Les performances sont de la plus haute importance étant donné le nombre d'ensembles de données à comparer.
Ajout de faits supplémentaires en fonction des discussions:
L'une ou l'autre des listes sera-t-elle la même pour de nombreux tests? Il fait comme l'un d'eux est une table de recherche statique.
Doit-il être une liste? Ce n'est pas le cas - la table de recherche statique peut être tout ce qui fonctionne le mieux. Le dynamique est un dict à partir duquel nous extrayons les clés pour effectuer une recherche statique.
Quelle serait la solution optimale compte tenu du scénario?
Réponses:
La fonction performante fournie par Python pour cela est
set.issubset
. Il comporte cependant quelques restrictions qui ne permettent pas de savoir si c'est la réponse à votre question.Une liste peut contenir des éléments plusieurs fois et a un ordre spécifique. Un ensemble ne le fait pas. De plus, les ensembles ne fonctionnent que sur les objets hachables .
Demandez-vous un sous-ensemble ou une sous-séquence (ce qui signifie que vous voudrez un algorithme de recherche de chaîne)? L'une ou l'autre des listes sera-t-elle la même pour de nombreux tests? Quels sont les types de données contenus dans la liste? Et d'ailleurs, faut-il que ce soit une liste?
Votre autre article croise un dict et une liste a rendu les types plus clairs et a obtenu une recommandation d'utiliser les vues clés du dictionnaire pour leurs fonctionnalités de type ensemble. Dans ce cas, il était connu pour fonctionner parce que les clés de dictionnaire se comportent comme un ensemble (à tel point qu'avant d'avoir des ensembles en Python, nous utilisions des dictionnaires). On se demande comment la question est devenue moins précise en trois heures.
la source
la source
set(a).issubset(b)
parce que dans ce cas, vous ne convertissez qu'ena
set mais pasb
, ce qui fait gagner du temps. Vous pouvez utilisertimeit
pour comparer le temps consommé dans deux commandes. Par exemple,timeit.repeat('set(a)<set(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
ettimeit.repeat('set(a).issubset(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
issubset
faire est de vérifier si l'argument est unset
/frozenset
, et si ce n'est pas le cas, il le convertit en temporaireset
pour comparaison, exécute la vérification, puis jette le temporaireset
. Les différences de temps (le cas échéant) seraient un facteur de petites différences dans les coûts de recherche LEGB (trouverset
une deuxième fois est plus cher que la recherche d'attribut sur un existantset
), mais c'est surtout un lavage pour des entrées suffisamment grandes.Explication: Générateur créant des booléens en parcourant la liste en
one
vérifiant si cet élément est dans la listetwo
.all()
renvoieTrue
si chaque élément est véridique, sinonFalse
.Il y a aussi un avantage qui
all
renvoie False sur la première instance d'un élément manquant plutôt que d'avoir à traiter chaque élément.la source
set(one).issubset(set(two))
c'est une excellente solution. Avec la solution que j'ai publiée, vous devriez pouvoir l'utiliser avec tous les objets s'ils ont les bons opérateurs de comparaison définis.all
de se court-circuiter correctement, le second effectuera tous les contrôles même s'il serait clair dès le premier contrôle que le test échouerait. Laissez simplement tomber les crochets pour obtenirall(x in two for x in one)
.En supposant que les éléments sont hachables
Si vous ne vous souciez pas des éléments en double, par exemple.
[1, 2, 2]
et[1, 2]
puis il suffit d' utiliser:.issubset
sera le moyen le plus rapide de le faire. Vérifier la longueur avant le testissubset
n'améliorera pas la vitesse car vous avez encore des éléments O (N + M) à parcourir et à vérifier.la source
Une autre solution serait d'utiliser un fichier
intersection
.L'intersection des ensembles contiendrait de
set one
(OU)
la source
Si list1 est dans la liste 2:
(x in two for x in one)
génère une liste deTrue
.quand on fait a un
set(x in two for x in one)
seul élément (True).la source
La théorie des ensembles est inappropriée pour les listes car les doublons entraîneront de mauvaises réponses en utilisant la théorie des ensembles.
Par exemple:
n'a pas de sens. Oui, cela donne une fausse réponse, mais ce n'est pas correct car la théorie des ensembles ne fait que comparer: 1,3,5 contre 1,3,4,5. Vous devez inclure tous les doublons.
Au lieu de cela, vous devez compter chaque occurrence de chaque élément et effectuer une vérification supérieure à égale. Ce n'est pas très coûteux, car il n'utilise pas d'opérations O (N ^ 2) et ne nécessite pas de tri rapide.
Ensuite, en exécutant ceci, vous obtenez:
la source
Puisque personne n'a envisagé de comparer deux chaînes, voici ma proposition.
Vous pouvez bien sûr vouloir vérifier si le tube ("|") ne fait pas partie de l'une ou l'autre des listes et peut-être choisi automatiquement un autre caractère, mais vous avez eu l'idée.
Utiliser une chaîne vide comme séparateur n'est pas une solution car les nombres peuvent avoir plusieurs chiffres ([12,3]! = [1,23])
la source
Pardonnez-moi si je suis en retard à la fête. ;)
Pour vérifier si l'un
set A
est un sous-ensemble deset B
,Python
aA.issubset(B)
etA <= B
. Cela fonctionneset
uniquement et fonctionne très bien MAIS la complexité de la mise en œuvre interne est inconnue. Référence: https://docs.python.org/2/library/sets.html#set-objectsJe suis venu avec un algorithme pour vérifier s'il
list A
s'agit d'un sous-ensemble deslist B
remarques suivantes.sort
commencer par les deux listes avant de comparer les éléments pour se qualifier pour un sous-ensemble.break
laloop
lorsque la valeur de l' élément de deuxième listeB[j]
est supérieure à la valeur de l' élément de la première listeA[i]
.last_index_j
est utilisé pour démarrerloop
surlist B
où il avait laissé la dernière. Cela permet d'éviter de commencer les comparaisons depuis le début delist B
(ce qui est, comme vous pourriez le deviner inutile, de commencerlist B
par laindex 0
suiteiterations
.)La complexité sera à la
O(n ln n)
fois pour le tri des deux listes etO(n)
pour la vérification du sous-ensemble.O(n ln n) + O(n ln n) + O(n) = O(n ln n)
.Le code contient de nombreuses
print
instructions pour voir ce qui se passe à chacuniteration
desloop
. Ceux-ci sont uniquement destinés à la compréhension.Vérifiez si une liste est un sous-ensemble d'une autre liste
Production
la source
Le code ci-dessous vérifie si un ensemble donné est un "sous-ensemble approprié" d'un autre ensemble
la source
En python 3.5, vous pouvez faire un
[*set()][index]
pour obtenir l'élément. C'est une solution beaucoup plus lente que les autres méthodes.ou juste avec len et set
la source
Voici comment je sais si une liste est un sous-ensemble d'une autre, la séquence m'importe dans mon cas.
la source
La plupart des solutions considèrent que les listes ne comportent pas de doublons. Si vos listes ont des doublons, vous pouvez essayer ceci:
Cela garantit que la sous-liste n'a jamais d'éléments différents d'une liste ou d'une plus grande quantité d'un élément commun.
la source
Si vous demandez si une liste est "contenue" dans une autre liste, alors:
Si vous demandez si chaque élément de listA a un nombre égal d'éléments correspondants dans listB, essayez:
la source
Si
a2 is subset of a1
, alorsLength of set(a1 + a2) == Length of set(a1)
la source