2009-04-26 12 views
6

私はオブジェクトのリストを取得しようとしており、そのリストを辞書に変換しようとしています。 dict値はリスト内の各オブジェクトになり、dictキーは各オブジェクトにある値になります。ここでリストをdictに変換する最も良い方法は、キーは各オブジェクトの値ですか?

はイムがやって何を表すいくつかのコードです:

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 

今そのコードは動作しますが、そのビット醜い、と少し遅いです。誰かがより速く/ "より良い"ものの例を挙げることができますか?

編集: ありがとう、返信ありがとうございます。私はより多くのpythonicの方法を見て驚いていると言わなければならないは、が手作りの方法よりも遅いようだ。

edit2: 申し訳ありませんが、私は非常に多くのテストhehで、より読みやすくするためにテストコードを更新しました。

ここで私たちはコードに関して言及していますが、私はコードに作者を入れています。

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]" 

と50と::

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]" 

そして最後に、500個のオブジェクトと:

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]" 
私は結果を取得しています、リスト内の5つのオブジェクトで

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)) 

お返事いただきありがとうございます!私は非常に結果に驚いた。 もっと速い方法のための他のヒントがあれば、私はそれらを聞きたいと思うでしょう。皆さんありがとう!

Python 3.0で
+0

あなたはまた、ここで提案をチェックアウトする必要があります、彼らは非常に似ています:http://stackoverflow.com/questions/753986/is-there-a-more-pythonic-way-to-build-this-dictionary/ 754154#754154 –

答えて

13

あなたはdictの内包表記を使用することができます。これは、Pythonの2にも可能である

{an_object.name : an_object for an_object in object_list} 

を、それは少し醜いです:

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

Hey、nice、3.0でdict comprehensionを追加したことを知らなかった – hyperboreean

+3

リストを作成する必要はありません(Python 2.4以降)。 dictコンストラクタにリストの理解を与える代わりに、シーケンスを一度しか反復しないジェネレータ式を使用してください: dict(object_listの項目のitem.name、item) – bignose

+0

@bignose - 正しいです。それを行う方法についてはJohn Fouyの答えを参照してください。 –

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

+1 Python 2でこれを行う良い方法です。 –

+5

+1:また、izipを使用すると、時間と空間を節約することができます。リストが非常に長い場合は重要です。 –

7

あなたが気になる場合スピードがあれば、少し改善することができます。あなたの "冗長"なソリューション(本当にうまくいく)は、中間のデータ構造を作成しません。一方、hyperboreeanのソリューションでは、

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

は2つの不要なリストを作成します。[o.name for o in object_list]は、リストを作成し、zip(_, _)は別のリストを作成します。これらのリストは両方とも、ディクテーションの作成時に1回だけ反復処理されます。

我々はジェネレータ式とリストの内包表記を置き換えることにより、1つのリストの作成を避けることができます:itertools.izipzipの交換

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

はイテレータを返すと、第二のリストを作成しないようにします:

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

同様に、角カッコを削除するだけで、Jason Bakerのソリューションを変更できます。

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

それは本当にいいですね。 – hyperboreean

関連する問題