代码之家  ›  专栏  ›  技术社区  ›  Lee Olayvar

将列表转换为dict的最佳方法,其中键是每个对象的值?

  •  6
  • Lee Olayvar  · 技术社区  · 17 年前

    下面是一些表示我所做工作的代码:

    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
    

    现在代码可以工作了,但是有点难看,而且有点慢。谁能举一个更快/更好的例子?

    好的,谢谢你的回复。我必须说,我很惊讶看到更多的蟒蛇方式 似乎

    编辑2:

    这里是我们在代码方面的位置,我在代码中加入了作者,如果我弄错了,请告诉我。

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

    列表中有5个对象,我得到的结果是:

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

    感谢你的回答!我对结果感到非常惊讶。

    3 回复  |  直到 17 年前
        1
  •  13
  •   Jason Baker    17 年前

    在python 3.0中,您可以使用dict理解:

    {an_object.name : an_object for an_object in object_list}
    

    这在Python 2中也是可能的,但有点难看:

    dict([(an_object.name, an_object) for an_object in object_list])
    
        2
  •  8
  •   hyperboreean    17 年前
    d = dict(zip([o.name for o in object_list], object_list))
    
        3
  •  7
  •   John Fouhy    17 年前

    如果你关心速度,那么我们可以稍微改进一下。您的“详细”解决方案(非常好)不创建中间数据结构。另一方面,hyperboreean的解决方案,

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

    [o.name for o in object_list] 创建一个列表,然后 zip(_, _) 创建另一个列表。在创建dict时,这两个列表仅用于迭代一次。

    我们可以通过使用生成器表达式替换列表理解来避免创建一个列表:

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

    zip 具有 itertools.izip 将返回迭代器并避免创建第二个列表:

    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)