2009-04-26 16 views
6

Nesnelerin bir listesini almaya çalışıyorum ve bu listeyi bir dikte haline getiriyorum. Dict değerleri listedeki her nesne olur ve dict tuşları her nesnede bulunan bir değer olur.Listeyi bir dict'e çevirmenin en iyi yolu, tuşların her bir nesnenin değeri olduğu yer?

İşte im ne yapıyor temsil eden bazı kod şudur:

class SomeClass(object): 

    def __init__(self, name): 
     self.name = name 

object_list = [ 
    SomeClass(name='a'), 
    SomeClass(name='b'), 
    SomeClass(name='c'), 
    SomeClass(name='d'), 
    SomeClass(name='e'), 
] 

object_dict = {} 
for an_object in object_list: 
    object_dict[an_object.name] = an_object 

Şimdi bu kod çalışır, ancak onun biraz çirkin ve biraz yavaş. Daha hızlı/"daha iyi" olan bir şeye örnek verebilir misiniz?

düzenleme: Pekala, cevaplar için teşekkürler. Ben el yapımı yoldan daha yavaş görünüyor daha pythonic yolları görmek için sürpriz olduğumu söylemeliyim.

edit2: Pekala, test kodunu, birçok test heh ile biraz daha okunabilir hale getirmek için güncelledim.

Burada kod bakımından olduğumuz yer var, kodları yazarlara koydum ve eğer herhangi bir şeyle uğraşırsam lütfen bana bildirin.

Example #1 Result: "[1.2428441047668457, 1.2431108951568604]" 
    Example #2 Result: "[3.3567759990692139, 3.3188660144805908]" 
    Example #3 Result: "[2.8346641063690186, 2.8344728946685791]" 
    Example #4 Result: "[3.0710639953613281, 3.0573830604553223]" 
    Example #5 Result: "[5.2079918384552002, 5.2170760631561279]" 
    Example #6 Result: "[3.240635871887207, 3.2402129173278809]" 
    Example #7 Result: "[3.0856869220733643, 3.0688989162445068]" 

ve 50 ile: son olarak

Example #1 Result: "[9.8108220100402832, 9.9066231250762939]" 
    Example #2 Result: "[16.365023136138916, 16.213981151580811]" 
    Example #3 Result: "[15.77024507522583, 15.771029949188232]" 
    Example #4 Result: "[14.598290920257568, 14.591825008392334]" 
    Example #5 Result: "[20.644147872924805, 20.64064884185791]" 
    Example #6 Result: "[15.210831165313721, 15.212569952011108]" 
    Example #7 Result: "[17.317100048065186, 17.359367847442627]" 

Ve 500 nesnelerle:

Example #1 Result: "[96.682723999023438, 96.678673028945923]" 
    Example #2 Result: "[137.49416589736938, 137.48705387115479]" 
    Example #3 Result: "[136.58069896697998, 136.5823769569397]" 
    Example #4 Result: "[115.0344090461731, 115.1088011264801]" 
    Example #5 Result: "[165.08325910568237, 165.06769108772278]" 
    Example #6 Result: "[128.95187497138977, 128.96077489852905]" 
    Example #7 Result: "[155.70515990257263, 155.74126601219177]" 
i sonucunu alıyorum listesinde 5 nesneler ile

from itertools import izip 
import timeit 

class SomeClass(object): 

    def __init__(self, name): 
     self.name = name 

object_list = [] 

for i in range(5): 
    object_list.append(SomeClass(name=i)) 

def example_1(): 
    'Original Code' 
    object_dict = {} 
    for an_object in object_list: 
     object_dict[an_object.name] = an_object 

def example_2(): 
    'Provided by hyperboreean' 
    d = dict(zip([o.name for o in object_list], object_list)) 

def example_3(): 
    'Provided by Jason Baker' 
    d = dict([(an_object.name, an_object) for an_object in object_list]) 

def example_4(): 
    "Added izip to hyperboreean's code, suggested by Chris Cameron" 
    d = dict(izip([o.name for o in object_list], object_list)) 

def example_5(): 
    'zip, improved by John Fouhy' 
    d = dict(zip((o.name for o in object_list), object_list)) 

def example_6(): 
    'izip, improved by John Fouhy' 
    d = dict(izip((o.name for o in object_list), object_list)) 

def example_7(): 
    'Provided by Jason Baker, removed brackets by John Fouhy' 
    d = dict((an_object.name, an_object) for an_object in object_list) 

timeits = [] 
for example_index in range(1, 8): 
    timeits.append(
     timeit.Timer(
      'example_%s()' % example_index, 
      'from __main__ import example_%s' % example_index) 
    ) 

for i in range(7): 
    timeit_object = timeits[i] 
    print 'Example #%s Result: "%s"' % (i+1, timeit_object.repeat(2)) 

Tüm cevaplara teşekkürler! Sonuçla çok şaşırdım. Daha hızlı bir yöntem için başka ipuçları varsa bunları duymayı çok isterim. Hepinize teşekkürler!

piton 3.0'da
+0

Burada da önerilere bir göz atmalısınız, çok benzerler: http://stackoverflow.com/questions/753986/is-there-a-more-pythonic-way-to-build-this-dictionary/ 754154 # 754154 –

cevap

13

Eğer dict anlama kullanabilirsiniz: Bu Python 2'de de mümkündür

{an_object.name : an_object for an_object in object_list} 

, ama biraz daha çirkin açıklanmıştır:

dict([(an_object.name, an_object) for an_object in object_list]) 
+0

Hey, güzel, 3.0 – hyperboreean

+3

'da dict anlayışını eklediklerini bilmiyordum. (Python 2.4 veya üstünde) gerek yok. Dict kurucusunu liste kavramasına vermek yerine, yalnızca bir kez diziyi yineleyen bir jeneratör ifadesi kullanın: dict (object_list öğesindeki öğe için (item.name, item)) – bignose

+0

Bignose - evet, siz haklısınız. Bunu yapmanın bir yolu için John Fouy'un cevabını görün. –

8
d = dict(zip([o.name for o in object_list], object_list)) 
+0

+1 Bunu Python 2'de yapmanın iyi bir yolu. 2. –

+5

+1: Ayrıca izip kullanıyorsanız, zaman ve alandan tasarruf edebilirsiniz, liste çok uzunsa önemli olabilir. –

7

Eğer endişeleniyorsanız Hızla, o zaman işleri biraz geliştirebiliriz. "Verbose" çözümünüz (ki bu gerçekten iyi) hiçbir orta veri yapısı yaratmıyor. [o.name for o in object_list] bir liste oluşturur ve zip(_, _) başka bir liste oluşturur: Diğer taraftan, hyperboreean çözeltisi, On

d = dict(zip([o.name for o in object_list], object_list)) 

iki gereksiz listeleri oluşturur. Bu listelerin her ikisi de, yalnızca, bir zamanların yaratılmasında, bir zamanlar üzerinde yinelenmeye hizmet eder.

Bir jeneratör ifade ile liste anlama değiştirerek tek bir liste oluşturulmasını önleyebilirsiniz

:

import itertools 
d = dict(itertools.izip((o.name for o in object_list), object_list)) 
:

d = dict(zip((o.name for o in object_list), object_list)) 

bir yineleyici dönmek ve ikinci bir liste yaratmaktan kaçınmak olacaktır itertools.izip ile zip Değiştirme

Jason Baker'ın çözümünü, aynı şekilde, köşeli parantezleri silerek de değiştirebiliriz:

d = dict((an_object.name, an_object) for an_object in object_list) 
+1

Bu doğru, güzel. – hyperboreean

İlgili konular