Best way to turn a list into a dict, where keys are the value of each object?

I am trying to take a list of objects and turn this list into a dict. The dict values ​​would be every object in the list, and the dict keys would be the value found in each object.

Here is what code represents what im is doing:

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 

Now this code works, but its a little ugly and a little slow. Can someone give an example of something faster / "better"?

edit: Ok, thanks for the answers. I have to say that I am surprised to see that more pythonic ways seem to be slower than a manual way.

edit2: Ok, I updated the test code to make it more readable, with so many hehe tests.

That's where we are in terms of code, I put the authors in code, and if I messed up everything, please let me know.

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

With 5 objects in the list, I get the result:

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

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

And finally, with 500 objects:

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

Thanks to everyone for answering! I was very surprised by the result. If there are any other tips for a faster method, I would love to hear them. Thanks everyone!

+6
python
source share
3 answers

In python 3.0 you can use dict comprehension:

 {an_object.name : an_object for an_object in object_list} 

This is also possible in Python 2, but it is a bit uglier:

 dict([(an_object.name, an_object) for an_object in object_list]) 
+13
source share
 d = dict(zip([o.name for o in object_list], object_list)) 
+8
source share

If you are concerned about speed, then we can improve the situation a bit. Your “detailed” solution (which is really fine) does not create intermediate data structures. Hyperborean solution, on the other hand,

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

creates two unnecessary lists: [o.name for o in object_list] creates a list, and zip(_, _) creates another list. Both of these lists are for repetition only once when creating a dict.

We can avoid creating a single list by replacing the list comprehension with a generator expression:

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

Replacing zip with itertools.izip will return an iterator and will not create a second list:

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

We could change Jason Baker's solution in the same way by simply removing the square brackets:

 d = dict((an_object.name, an_object) for an_object in object_list) 
+7
source share

All Articles