2013-08-17 5 views
16

ein Wörterbuch von Listen gegeben, wiePython: durch ein Wörterbuch mit Liste iterieren Werte

d = {'1':[11,12], '2':[21,21]} 

die mehr pythonic oder sonst vorzuziehen ist:

for k in d: 
    for x in d[k]: 
     # whatever with k, x 

oder

for k, dk in d.iteritems(): 
    for x in dk: 
     # whatever with k, x 

oder gibt es noch etwas anderes zu beachten?

BEARBEITEN, falls eine Liste nützlich sein sollte (z. B. Standarddikts behalten ihre Reihenfolge nicht bei), könnte dies angebracht sein, obwohl sie viel langsamer ist.

d2 = d.items() 
for k in d2: 
     for x in d2[1]: 
      # whatever with k, x 
+0

Ich bevorzuge die zweite, aber sie sind in etwa gleich klar. – bbayles

+0

Warum nicht viel mehr Python mit List Comprehensions? – woofmeow

+0

@woofmeow bitte klären – foosion

Antwort

11

Hier ist ein Speed-Test, warum nicht:

import random 
numEntries = 1000000 
d = dict(zip(range(numEntries), [random.sample(range(0, 100), 2) for x in range(numEntries)])) 

def m1(d): 
    for k in d: 
     for x in d[k]: 
      pass 

def m2(d): 
    for k, dk in d.iteritems(): 
     for x in dk: 
      pass 

import cProfile 

cProfile.run('m1(d)') 

print 

cProfile.run('m2(d)') 

# Ran 3 trials: 
# m1: 0.205, 0.194, 0.193: average 0.197 s 
# m2: 0.176, 0.166, 0.173: average 0.172 s 

# Method 1 takes 15% more time than method 2 

cProfile Beispiel Ausgabe:

  3 function calls in 0.194 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.194 0.194 <string>:1(<module>) 
     1 0.194 0.194 0.194 0.194 stackoverflow.py:7(m1) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 



     4 function calls in 0.179 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.179 0.179 <string>:1(<module>) 
     1 0.179 0.179 0.179 0.179 stackoverflow.py:12(m2) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     1 0.000 0.000 0.000 0.000 {method 'iteritems' of 'dict' objects} 
+2

iteritems() ist ein bisschen schneller und hat 'iter' in seinem Namen . Was könnte man mehr fragen? :-) – foosion

+0

Auf meinem Rechner erhalte ich mit Ihrem Code 0,172 für m2 und 0,185 für m2. – foosion

+0

Wie seltsam - ich habe es ein paar Mal probiert, und m1 nimmt konsistent rund 15% mehr Zeit auf meinem Rechner. Python 2.7, Intel i5. – Brionius

1

Hier ist die Liste Verständnis Ansatz. Verschachtelte ...

r = [[i for i in d[x]] for x in d.keys()] 
print r 

[[11, 12], [21, 21]] 
+0

Für so etwas scheint d.items() besser zu sein, zumindest für mich, vor allem, wenn Sie etwas mit den Schlüsseln und den Werten tun wollen. – foosion

+0

Nun, richtig .. Ich weiß nicht wirklich, was Ihr Anwendungsfall ist. Sie haben @woofmeow um Erläuterungen zu den Listenkompressen gebeten. – kelorek

+0

Keine Sorge. Ich nehme an, dass ich wirklich gefragt habe, wie ein Listenverständnis auf eine Frage reagiert, die (wie bearbeitet) etwas mit dem Schlüssel und den Werten tun will. – foosion

2

Meine Ergebnisse aus Brionius Code:

  3 function calls in 0.173 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.173 0.173 <string>:1(<module>) 
     1 0.173 0.173 0.173 0.173 speed.py:5(m1) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Prof 
iler' objects} 


     4 function calls in 0.185 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.185 0.185 <string>:1(<module>) 
     1 0.185 0.185 0.185 0.185 speed.py:10(m2) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Prof 
iler' objects} 
     1 0.000 0.000 0.000 0.000 {method 'iteritems' of 'dict' obje 
cts} 
2

hielt ich ein paar Methoden:

import itertools 

COLORED_THINGS = {'blue': ['sky', 'jeans', 'powerline insert mode'], 
        'yellow': ['sun', 'banana', 'phone book/monitor stand'], 
        'red': ['blood', 'tomato', 'test failure']} 

def forloops(): 
    """ Nested for loops. """ 
    for color, things in COLORED_THINGS.items(): 
     for thing in things: 
      pass 

def iterator(): 
    """ Use itertools and list comprehension to construct iterator. """ 
    for color, thing in (
     itertools.chain.from_iterable(
      [itertools.product((k,), v) for k, v in COLORED_THINGS.items()])): 
     pass 

def iterator_gen(): 
    """ Use itertools and generator to construct iterator. """ 
    for color, thing in (
     itertools.chain.from_iterable(
      (itertools.product((k,), v) for k, v in COLORED_THINGS.items()))): 
     pass 

I verwendet ipython und memory_profiler Leistung zu testen:

>>> %timeit forloops() 
1000000 loops, best of 3: 1.31 µs per loop 

>>> %timeit iterator() 
100000 loops, best of 3: 3.58 µs per loop 

>>> %timeit iterator_gen() 
100000 loops, best of 3: 3.91 µs per loop 

>>> %memit -r 1000 forloops() 
peak memory: 35.79 MiB, increment: 0.02 MiB 

>>> %memit -r 1000 iterator() 
peak memory: 35.79 MiB, increment: 0.00 MiB 

>>> %memit -r 1000 iterator_gen() 
peak memory: 35.79 MiB, increment: 0.00 MiB 

Wie Sie sehen können e, die Methode hatte keinen beobachtbaren Einfluss auf die Spitzenspeicherauslastung, aber verschachtelte for Loops waren unschlagbar für die Geschwindigkeit (ganz zu schweigen von der Lesbarkeit).

Verwandte Themen