2015-07-19 3 views
4

Я сейчас делаю программу, и я искал ее, но я не могу найти решение; Моя проблема заключается в том, где я хочу сделать условие, когда все выбранные переменные не равны, и я могу это сделать, но только с длинными строками текста, есть ли более простой способ? Мое решение до сих пор это делать:Тест Python, если все переменные N различны

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

Но я хочу сделать это для нескольких групп от пяти переменных, и это становится весьма запутанной, что многие. Что я могу сделать, чтобы сделать его проще?

+1

Что вы на самом деле делаете, что требует от вас, чтобы проверить, что многие условия? У этого есть немного запаха кода. – Makoto

+1

Я согласен с @ Макото. Что требует от вас этого? Это звучит как проблема xy. – Carcigenicate

+0

Это программа, которая проверяет голоса 5 кандидатов, в основном подсчитывает список, который имеет предпочтение голосов от 1 до 5, тот, который имеет наибольшее количество голосов «1», выбирается победителем, но если один или несколько имеют ту же сумму голосов «1» затем выбирает победителя на основании «2» голосов предпочтений, и если они одинаковы, то это «3» голоса и так далее. Это немного длинный, но это была заданная задача, и я все это разбираюсь отдельно от этой части кода. –

ответ

18

Создать набор и проверить, является ли число элементов в наборе такое же, как число переменных в списке, что вы перешли в него:

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

Набор не повторяющихся элементов так если вы создаете набор и имеет такое же количество элементов, сколько количество элементов в исходном списке, то вы знаете, что все элементы отличаются друг от друга.

+8

, предполагая, что объекты хешируются. –

+3

Это также сначала создает весь набор, таким образом, не может быть неудачным раньше. Цикл for может уже прерываться, когда первые два элемента отличаются. Таким образом, среднее время выполнения зависит от того, насколько часто в данных ожидаются различия. –

+0

Хотя это может быть хорошим ответом, я чувствую, что это действительно не затрагивает актуальную проблему. Ответчик должен вернуться (надеюсь), чтобы уточнить, но такой ответ мог бы только смутить, чем помочь чему-либо. – Makoto

5

Если вы можете хэш-переменные (и, ну, ваши переменные имеют смысл __hash__), используйте набор.

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) наихудший случай. (И да, я знаю, что вы также можете len(li) == len(set(li)), но этот вариант возвращается рано, если совпадение найдено)

Если вы не можете хэш своих значений (по любой причине), но может быть осмысленно сравнить их:

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), потому что сортировка. В принципе, сортировать все и сравнивать попарно. Если две вещи равны, они должны были сортироваться рядом друг с другом. (Если по какой-либо причине ваш __cmp__ не сортирует вещи, которые являются одинаковыми рядом друг с другом, 1. wut и 2. пожалуйста, переходите к следующему методу.)

И если ne является единственным оператором, у вас есть ....

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 

Я в основном с помощью itertools.combinations на пары все переменные, а затем с помощью operator.ne для проверки не-equalness. Это имеет худшую временную сложность O (n^2), хотя она все еще должна быть короткой (потому что генераторы и all ленивы). Если вы абсолютно уверены, что и eq являются противоположностями, вы можете вместо этого использовать operator.eq и any.

Добавление: Vincent написал много более читаемой версии itertools варианта, который выглядит как

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 

Добавление 2: Мм, при достаточно большие наборы данных, сортировки вариант должен возможно использовать heapq. Все еще был бы O (nlogn) худший случай, но O (n) лучший случай. Это было бы что-то вроде

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

Я не думаю, что это так уродливо, особенно если вы избавитесь от 'operator.ne'. Что-то вроде 'all (a! = B для a, b в комбинациях (lst, 2))'. – Vincent

0

Поместите значения в тип контейнера. Затем просто пройдите через контейнер, сравнивая каждое значение. Это потребовало бы O (n^2).

псевдо-код:

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

Еще лучше, почему бы не начать с массива на первом месте. Это идеально подходит для переменных, которые тесно связаны, например, ваш случай, когда вам нужно сравнить список переменных друг с другом. – jax

+1

Но создание 'set (variables)' - это только O (n) и очень быстрое O (n) при этом. – smci

+0

Да, я не это учитывал. Да, возможно, он мог бы оптимизировать. – jax

0

Вы можете перечислить список и убедитесь, что все значения первого появления этого значения в списке:

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

Это позволяет короткое замыкание, как только первый дубликат обнаружен из-за поведения функции all() Python.

Или то же самое, перечислить список и проверить, есть ли какие-либо ценности, которые не являются первым появлением этого значения в списке:

a = [5, 15, 20, 65, 48] 
if not any(a.index(v) != i for i, v in enumerate(a)): 
    print "all elements are unique" 
Смежные вопросы