2015-08-30 18 views
6

Zastanawiam się, czy jest możliwe, aby uzyskać taki sam efekt, jak z tego kodu:python - sprawdzić, czy każda wartość dict nie jest None (bez iteratory)

d = {'a':None,'b':'12345','c':None} 
nones=False 
for k,v in d.items(): 
    if d[k] is None: 
    nones=True  

lub

any([v==None for v in d.values()]) 

ale bez iteratora pętli for lub generatora?

+4

Nie można sprawdzić wartości na liście bez wykonywania iteracji .. – Maroun

+1

Należy sprawdzić wszystkie wartości; co dokładnie jest nie tak z zapętleniem? –

+0

Nie potrzebujesz zrozumienia listy. Po prostu 'any (d.values ​​())'. Ale ta pętla wewnętrznie. Nie ma sposobu na uniknięcie tego. – juanchopanza

Odpowiedz

5

Możesz mieć Python do zapętlenia kodu C za pomocą dictionary view; to robi test członkostwa przed wszystkimi wartościami bez tworzenia nowej listy:

if None not in d.viewvalues(): 

W Pythonie 3, dict.values() zwraca widok słownika zbyt.

Demo Pythonie 2:

>>> d = {'a': None, 'c': None, 'b': '12345'} 
>>> None not in d.viewvalues() 
False 

ta pętla na wartości aż zostanie znaleziona, jak liście lub członków odpowiedniego testu any(), dzięki czemu jest to O (N) testu. Różni się to od słownika lub ustawieniem testu członkostwa, w którym można użyć skrótu, aby średnio wykonać test kosztowy.

Nie używałeś poprawnie any(); drop wsporniki [...]:

if any(v is not None for v in d.itervalues()): # Python 3: use d.values() 

Jeśli twoim celem jest przetestowanie pewnych wartości, i trzeba unikać stałego pętle dla każdego testu, należy rozważyć utworzenie indeksu odwrotnego zamiast:

inverse_index = {} 
for key, value in d.items(): 
    inverse.setdefault(value, set()).add(key) 

ten wymaga jednak, aby wartości były nieosiągalne. Teraz możesz po prostu przetestować każdą wartość:

if None not in inverse_index: 

w O (1) czasie.

+0

Co powiesz na 'any (map (lambda x: x to nie None, d.values ​​()))' która jest bardziej wydajna w Pythonie 3 i działa również w Pythonie 2? –

+0

@NiklasR: 'x jest Brak', z pewnością. Wywołanie "lambda" również kosztuje, nie jestem pewna, że ​​jest to o wiele bardziej wydajne, niż warte tego. –

+0

@NiklasR jest gorzej niż przy wariancie python3 (używając 'values ​​()'), który utworzy brzydką listę w Pythonie 2, ale potem użyje tego w wyrażeniu generatora kontra twoja ostateczna pętla dwa razy, tworząc dodatkową listę, a tym samym marnując więcej . – deets

6

Można użyć

nones = not all(d.values()) 

Jeśli wszystkie wartości nie są None, nony będzie ustawiona na False, inny True. Jest to po prostu abstrakcja, wewnętrznie musi być iterowana na liście wartości.