Comment puis-je vérifier que la liste a un et un seul truthy valeur?
En python, j'ai une liste qui devrait avoir un et un seul truthy valeur (qui est, bool(value) is True
). Est-il un moyen astucieux pour vérifier cela? Maintenant, je suis juste une itération à travers la liste et vérifier manuellement:
def only1(l)
true_found = False
for v in l:
if v and not true_found:
true_found=True
elif v and true_found:
return False #"Too Many Trues"
return true_found
Cela semble peu élégante et pas très pythonic. Est-il un meilleur moyen pour ce faire?
Je pense que votre solution est très fin et il est pythonic!
Common Lisp:
POUR être claire: voulez-vous vérifier qu'il n'existe qu'un
Common Lisp:
(= 1 (count-if #'identity list))
.sum(lst) == 1
POUR être claire: voulez-vous vérifier qu'il n'existe qu'un
True
ou un seul truthy valeur?OriginalL'auteur Matthew Scouten | 2013-05-28
Vous devez vous connecter pour publier un commentaire.
Le niveau le plus détaillé de la solution n'est pas toujours le plus unelegant solution. Donc j'ajoute juste une modification mineure (dans l'ordre pour sauver un peu redondant boolean évaluations):
Voici quelques timings pour la comparaison:
Ma sortie:
Comme on le voit, l'OP solution est nettement mieux que la plupart des autres solutions posté ici. Comme prévu, les meilleurs sont ceux de court-circuit comportement, surtout que la solution posté par Jon Clements. Au moins pour le cas de deux au début de la
True
valeurs dans une liste.Ici le même pour ne
True
valeur:Je n'ai pas vérifier la signification statistique, mais c'est intéressant, cette fois, les approches proposées par F. J., et surtout celle de Jon Clements apparaître de nouveau à être nettement supérieure.
0.446
le plus rapide?c'est pourquoi j'ai écrit plus, il fait plus clair maintenant. (la plupart des de l'posté, pas plus de l'essai...)
Je soupçonne JonClement est si vite parce que la plupart des
any
est implémenté en C+1 Pour votre ouverture de ligne. Toutes les réponses avec
sum
sont en fait pire que l'OP est simple et directe de code ..J'ai ajouté les deux une section sur la lisibilité et de l'élégance (court, il est vrai) et sur l'évaluation de la performance. Que la question posée par l'intelligence les deux aspects devraient faire l'objet d'un examen, je pense. Comme je le vois, j'ai apporté une réponse à l'adresse de ces deux aspects de cette question. Si vous vous sentez cette réponse n'est pas utile, n'hésitez pas à downvote.
OriginalL'auteur moooeeeep
Qui ne demande pas importations:
Sinon, peut-être une version plus lisible:
Ce:
i
une vrai valeurcomme pour la consommation de l'itératif.
any
sera comme par docs return True dès qu'une non-valeur false est trouvé. Après cela, nous recherchons pour une valeur vraie de nouveau, et le cas échéant de le traiter comme un échec... Donc ce sera du travail pour vider les listes, les listes/autres séquences, et tout objet iterable...Effets secondaires de briser tous les théorèmes!
x and not x = False
est correcte uniquement six
est referentially transparent.C'est pas un détail d'implémentation de
any()
- c'est une fonctionnalité documentée de la fonction, et la garantie de la fonctionnalité de mise en œuvre conforme à l'Python spec.Quiconque pense que ce n'est pas lisible une solution devriez considérer ceci: Il est concis et ne repose que sur des comportements connus et communs construire de Python. Juste parce qu'un noob ne serait pas le comprendre, ne pas le rendre lisible. Il est également un excellent moyen d'apprendre ce qui doit être connu, car il incite à la curiosité immédiate à ceux qui ne voient pas comment il fonctionne.
OriginalL'auteur Jon Clements
Cela dépend si vous êtes juste à la recherche de la valeur
True
ou sont aussi à la recherche de valeurs qui permettrait d'évaluer àTrue
logiquement (comme11
ou"hello"
). Si l'ancien:Si ce dernier:
ce qui permettrait de faire les deux, le comptage et la conversion en une seule itération, sans avoir à construire une nouvelle liste.
list(map(bool, l)).count(True)
Cette recherche du sens littéral du Vrai, pas à d'autres, les vraies valeurs (c'est à dire: positif ints pas de récipients vides, etc)
Juste pour signaler à l'OP, ce ne sera probablement pas de court-circuit lorsque plus d'une valeur "True" est trouvé, de sorte que leur code peut leur donner plus d'efficacité dans certaines circonstances.
La deuxième fonction peut être écrite comme
return sum(bool(e) for e in l) == 1
.bool
sous-classesint
et Vrai/Faux se comporter comme 1/0 concernant l'arithmétique.Je voudrais éviter d'utiliser
l
comme un nom de variable (il ressemble un peu trop à1
ici), et je voudrais réécriresum(bool(e) for e in l)
commesum(1 for e in l if e)
OriginalL'auteur David Robinson
Une ligne de réponse qui conserve le court-circuit comportement:
Ce sera nettement plus rapide que les autres solutions ici pour de très grandes iterables qui ont deux ou plus vraies valeurs relativement tôt.
ifilter(None, itr)
donne un objet iterable qui ne cèdent truthy éléments (x
est truthy sibool(x)
retourneTrue
).islice(itr, 2)
donne un objet iterable qui ne cèdent les deux premiers éléments deitr
. Par la conversion d'une liste et vérifier que la longueur est égale à un, nous pouvons vérifier que exactement un truthy élément existe sans avoir besoin de vérifier les éléments, après que nous avons trouvé deux.Voici quelques timing des comparaisons:
De code de configuration:
Présentant de court-circuit comportement:
Grande liste de court-circuit ne se produit pas:
Petite liste:
De sorte que le
sum()
approche est plus rapide pour les très petites listes, mais comme la liste d'entrée est importante, plus ma version est plus rapide, même en cas de court-circuit n'est pas possible. En cas de court-circuit est possible sur une grande entrée, la différence de performances est clair.Jusqu'vote pour le style, et en conservant le court-circuit. Mais c'est plus difficile à lire.
+1. Le seul à reproduire l'OP intention de court-circuit.
+1 si vous fournissez certains
timeit
expérimentation pour un objectif de performance de comparaison pour l'OP solution.Naïvement si vous avait une infinie itératif qui a deux
True
valeurs quelque part "dès le début", ce sera fini, par rapport aux autres réponses tourner leurs roues toujours en essayant d'obtenir le nombre.OriginalL'auteur Andrew Clark
Je voulais gagner le nécromancien badge, donc j'ai généralisé le Jon Clements excellente réponse, en préservant les avantages de court-circuiter la logique et rapide prédicat de la vérification avec toute et tous.
Donc, ici, est:
N(trues) = n
N(trues) <= n:
N(trues) >= n:
m <= N(trues) <= n
OriginalL'auteur Antti Haapala
Il est difficile d'être sûr de sûr, mais ma théorie est que beaucoup de n00b python pour les programmeurs - peut-être ceux avec Java arrière-plan, en particulier - se sentir plus à l'aise avec plus de la syntaxe. (Moi, je l'habitude d'être un peu comme ça il y a 5-10 ans, mais aujourd'hui, je considère que c'est un manque de professionnalisme et ignorants.) +1
OriginalL'auteur gariel
Que vous pouvez faire:
Ou
Bâtiment sur @JoranBeasley de la méthode:
OriginalL'auteur karthikr
Si il y a un seul
True
, alors la longueur de laTrue
s doit être un:OriginalL'auteur Marc Laugharn
Cela semble fonctionner et devrait être en mesure de gérer n'importe quel itérable, pas seulement
list
s. Il les courts-circuits, chaque fois que possible afin de maximiser l'efficacité. Fonctionne dans les deux Python 2 et 3.De sortie:
iter(x for x in my_list if x)
et puis, à l'aide denext
, peut-être plus agréable que d'utilisermap
etlist.index
Bien que je n'ai pas utilisé l'approche que vous avez suggéré, votre commentaire m'a inspiré pour réviser ma réponse originale à cette question et de le rendre encore plus progressive dans la nature et se débarrasse de la
map
etlist.index
.+1 oui, c'est encore plus clair
OriginalL'auteur martineau
(En supposant que tous vos valeurs sont booleanish.)
Ce serait probablement plus rapide en résumé
bien qu'il peut causer quelques problèmes, selon les types de données dans votre liste.
Ok 😛
OriginalL'auteur Joran Beasley
@JonClements solution étendue pour au plus N valeurs Vraies:
edit: meilleure version
edit2: inclure au moins m de True et au plus n de True
iterable.count(True) = 3
,NTrue(iterable, 1) = False
,NTrue(iterable, 2) = False
,NTrue(iterable, 3) = True
,NTrue(iterable, 4) = True
, ... essentiellement, Il s'étend de laand not any(i)
partie deand not any(i) and not any(i) and not...
Ne pas
all(any(i) for i in xrange(n)) and not any(i)
travailler ici?qui ne renvoie Vrai pour exactement n vrai. Il m'a donné l'idée de somme au cours de la
any
s, si.Vous dire plutôt
any(i) and not all(any(i) for x in xrange(n))
?N'est-ce pas
True and not all(<n booleans>)
logiquement les mêmes quecount(True) <= n
? L'idée est toujours de tester le plus petit ensemble possible et de pause sur la première condition d'échec.OriginalL'auteur Nisan.H
Explication: Le
map
fonction des cartes d'une liste à une autre liste, en faisantTrue => 1
etFalse => 0
. Nous avons maintenant une liste de 0 et de 1, au lieu de Vrai ou de Faux. Maintenant, nous avons simplement la somme de cette liste et si il est à 1, il n'y a qu'un seul Vrai valeur.OriginalL'auteur Martin Konecny
À des fins d'exhaustivité, et de démontrer l'utilisation avancée de Python de contrôle de flux pour pour tour de boucle, on peut éviter le supplément de la comptabilité de la accepté de répondre, faisant à ceci un peu plus rapide.:
Au-dessus du flux de contrôle simple rend l'utilisation de Python est sophistiqué fonctionnalité de boucles: la
else
. La sémantique est que si vous avez fini de parcourir l'itérateur que vous consommez sansbreak
-ing hors d'elle, vous entrez alors dans leelse
bloc.Voici la accepté de répondre, qui utilise un peu plus de la comptabilité.
de temps ces:
Nous voyons donc que l'on a accepté la réponse est un peu plus longue (un peu plus d'un an et demi de un pour cent).
Naturellement, en utilisant le haut -
any
, écrit en C, est beaucoup plus rapide (voir Jon Clement de réponse pour la mise en œuvre - c'est la forme courte):OriginalL'auteur Aaron Hall
Est-ce que vous cherchez?
OriginalL'auteur c-urchin
Temps linéaire. Utilise le Compteur intégré de classe, qui est ce que vous devriez utiliser pour vérifier le compte.
Re-lecture de votre question, il semble que vous voulez réellement pour vérifier qu'il n'est qu'un truthy valeur, plutôt qu'un
True
valeur. Essayez ceci:Alors que vous pouvez obtenir mieux dans le meilleur des cas les performances, rien n'a mieux pour le pire des cas la performance. C'est aussi court et facile à lire.
Voici une version optimisée pour de meilleures performances:
Le pire des cas, la performance a une forte
k
(comme dansO(kn+c)
), mais il est complètement général.Voici un ideone à expérimenter avec des performances: http://ideone.com/ZRrv2m
OriginalL'auteur Marcin
Voici quelque chose qui devrait travailler pour rien truthy, si elle n'a pas de court-circuit. Je l'ai trouvé en cherchant un moyen propre à interdire mutuellement exclusifs arguments:
OriginalL'auteur Andrew
Ce sujet:
Si vous ne voulez compter boolean True valeurs.
OriginalL'auteur Radek Svoboda