2015-07-19 1 views
4

Je suis en train de faire un programme et j'ai cherché autour mais je ne trouve pas de solution; Mon problème est où je veux faire une condition où toutes les variables sélectionnées ne sont pas égales et je peux le faire, mais seulement avec de longues lignes de texte, est-il un moyen plus simple? Ma solution est donc beaucoup à faire:Test Python si toutes les variables N sont différentes

if A!=B and A!=C and B!=C: 

Mais je veux le faire pour plusieurs groupes de cinq variables et il devient assez déroutant avec que beaucoup. Que puis-je faire pour le rendre plus simple?

+1

Que faites-vous réellement qui vous oblige à vérifier que de nombreuses conditions? Cela a une odeur de code. – Makoto

+1

Je suis d'accord avec @Makoto. Qu'est-ce qui vous oblige à faire cela? Cela ressemble à un problème de xy. – Carcigenicate

+0

Il s'agit d'un programme qui vérifie les votes de 5 candidats, il compte une liste qui a des votes de préférence de 1 à 5, celui avec le plus grand nombre de votes '1' est gagnant mais si un ou plusieurs ont le même de «1» votes, il choisit ensuite le gagnant sur la base des votes de préférence «2» et s'ils sont identiques, il fait «3» votes et ainsi de suite. C'est un peu long, mais c'était l'ensemble des tâches et j'ai tout séparé de cette partie du code. –

Répondre

18

Créer un ensemble et vérifier si le nombre d'éléments dans l'ensemble est le même que le nombre de variables dans la liste que vous avez passé en elle:

>>> variables = [a, b, c, d, e] 
>>> if len(set(variables)) == len(variables): 
...  print("All variables are different") 

Un ensemble n'a pas d'éléments en double si Si vous créez un ensemble et qu'il a le même nombre d'éléments que le nombre d'éléments de la liste originale, vous savez que tous les éléments sont différents les uns des autres.

+8

en supposant que les objets sont hashable –

+3

Cela crée également d'abord l'ensemble complet et donc ne peut pas échouer tôt. La boucle for peut déjà s'interrompre lorsque les deux premiers éléments sont différents. Le temps d'exécution moyen dépend donc de la fréquence à laquelle les différences sont attendues dans les données. –

+0

Bien que cela puisse être une bonne réponse, je pense que cela n'a pas vraiment résolu le problème réel. Le demandeur devrait revenir (espérons-le) pour clarifier, mais ce genre de réponse ne ferait que l'embrouiller davantage que de l'aider pour n'importe quoi. – Makoto

5

Si vous pouvez hacher vos variables (et, euh, vos variables ont un sens __hash__), utilisez un ensemble.

def check_all_unique(li): 
    unique = set() 
    for i in li: 
     if i in unique: return False #hey I've seen you before... 
     unique.add(i) 
    return True #nope, saw no one twice. 

O (n) pire cas. (Et oui, je suis conscient que vous pouvez également len(li) == len(set(li)), mais cette variante retourne au début si une correspondance est trouvée)

Si vous ne pouvez pas vos valeurs de hachage (pour une raison quelconque), mais peut les comparer de façon significative:

def check_all_unique(li): 
    li.sort() 
    for i in range(1,len(li)): 
     if li[i-1] == li[i]: return False 
    return True 

O (nlogn), parce que le tri. Fondamentalement, trier tout, et comparer par paire. Si deux choses sont égales, elles auraient dû être triées les unes à côté des autres. (Si, pour une raison quelconque, votre __cmp__ ne règle pas les choses qui sont les mêmes à côté de l'autre, 1. Wut et 2. S'il vous plaît passez à la méthode suivante.)

Et si ne est le seul opérateur que vous avez ....

import operator 
import itertools 
li = #a list containing all the variables I must check 
if all(operator.ne(*i) for i in itertools.combinations(li,2)): 
    #do something 

J'utilise essentiellement itertools.combinations pour apparier toutes les variables, puis en utilisant operator.ne pour vérifier non equalness. Cela a une complexité temporelle pire du cas de O (n^2), bien qu'il devrait toujours court-circuiter (parce que les générateurs, et all est paresseux). Si vous êtes absolument sûr que ne et eq sont opposés, vous pouvez utiliser operator.eq et any à la place.

Addendum: Vincent a écrit une beaucoup version plus lisible de la variante itertools qui ressemble à

import itertools 
lst = #a list containing all the variables I must check 
if all(a!=b for a,b in itertools.combinations(lst,2)): 
    #do something 

Addendum 2: Euh, pour les ensembles de données suffisamment grandes, la variante de tri devrait peut-être utiliser heapq. Toujours serait O (nlogn) le pire des cas, mais O (n) le meilleur des cas. Ce serait quelque chose comme

import heapq 
def check_all_unique(li): 
    heapq.heapify(li) #O(n), compared to sorting's O(nlogn) 
    prev = heapq.heappop(li) 
    for _ in range(len(li)): #O(n) 
     current = heapq.heappop(li) #O(logn) 
     if current == prev: return False 
     prev = current 
    return True 
+0

Je ne pense pas que ce soit moche, surtout si vous vous débarrassez de 'operator.ne'. Quelque chose comme 'all (a! = B pour a, b dans les combinaisons (lst, 2))'. – Vincent

0

Mettez les valeurs dans un type de conteneur. Il suffit ensuite de faire une boucle dans le conteneur, en comparant chaque valeur. Cela prendrait environ O (n^2).

code pseudo:

a[0] = A; a[1] = B ... a[n]; 

for i = 0 to n do 
    for j = i + 1 to n do 
     if a[i] == a[j] 
     condition failed 
+0

Mieux encore, pourquoi ne pas commencer par un tableau en premier lieu. Ceci est idéal pour les variables qui sont étroitement liées, comme c'est le cas lorsque vous devez comparer une liste de variables entre elles. – jax

+1

Mais créer 'set (variables)' est seulement O (n), et un O (n) très rapide à cela. – smci

+0

Oui, je n'ai pas cela en compte. Oui, on pourrait probablement optimiser. – jax

0

Vous pouvez énumérer une liste et vérifiez que toutes les valeurs sont la première occurrence de cette valeur dans la liste:

a = [5, 15, 20, 65, 48] 
if all(a.index(v) == i for i, v in enumerate(a)): 
    print "all elements are unique" 

Cela permet de court-circuiter une fois que la Le premier doublon est détecté en raison du comportement de la fonction all() de Python.

ou équivalent, énumérer une liste et vérifiez s'il y a des valeurs qui ne sont pas la première occurrence de cette valeur dans la liste:

a = [5, 15, 20, 65, 48] 
if not any(a.index(v) != i for i, v in enumerate(a)): 
    print "all elements are unique"