Reputation: 4950
I was sure that there would be a one liner to convert a list to a dictionary where the items in the list were keys and the dictionary had no values.
The only way I could find to do it was argued against.
"Using list comprehensions when the result is ignored is misleading and inefficient. A for
loop is better"
myList = ['a','b','c','d']
myDict = {}
x=[myDict.update({item:None}) for item in myList]
>>> myDict
{'a': None, 'c': None, 'b': None, 'd': None}
It works, but is there a better way to do this?
Upvotes: 6
Views: 1357
Reputation: 4610
Maybe you can use itertools:
>>>import itertools
>>>my_list = ['a','b','c','d']
>>>d = {}
>>>for x in itertools.imap(d.setdefault, my_list): pass
>>>print d
{'a': None, 'c': None, 'b': None, 'd': None}
For huge lists, maybe this is very good :P
Upvotes: 1
Reputation: 17733
You can use a list comprehension:
my_list = ['a','b','c','d']
my_dict = dict([(ele, None) for ele in my_list])
Upvotes: 1
Reputation: 882421
To answer the original questioner's performance worries (for lookups in dict
vs set
), somewhat surprisingly, dict
lookups can be minutely faster (in Python 2.5.1 on my rather slow laptop) assuming for example that half the lookups fail and half succeed. Here's how one goes about finding out:
$ python -mtimeit -s'k=dict.fromkeys(range(99))' '5 in k and 112 in k'
1000000 loops, best of 3: 0.236 usec per loop
$ python -mtimeit -s'k=set(range(99))' '5 in k and 112 in k'
1000000 loops, best of 3: 0.265 usec per loop
doing each check several times to verify they're repeatable. So, if those 30 nanoseconds or less on a slow laptop are in an absolutely crucial bottleneck, it may be worth going for the obscure dict.fromkeys
solution rather than the simple, obvious, readable, and clearly correct set
(unusual -- almost invariably in Python the simple and direct solution has performance advantages too).
Of course, one needs to check with one's own Python version, machine, data, and ratio of successful vs failing tests, and confirm with extremely accurate profiling that shaving 30 nanoseconds (or whatever) off this lookup will make an important difference.
Fortunately, in the vast majority of cases, this will prove totally unnecessary... but since programmers will obsess about meaningless micro-optimizations anyway, no matter how many times they're told about their irrelevance, the timeit
module is right there in the standard library to make those mostly-meaningless micro-benchmarks easy as pie anyway!-)
Upvotes: 5
Reputation: 258388
And here's a fairly wrong and inefficient way to do it using map:
>>> d = dict()
>>> map (lambda x: d.__setitem__(x, None), [1,2,3])
[None, None, None]
>>> d
{1: None, 2: None, 3: None}
Upvotes: 1
Reputation: 994231
You could use a set instead of a dict:
>>> myList=['a','b','c','d']
>>> set(myList)
set(['a', 'c', 'b', 'd'])
This is better if you never need to store values, and are just storing an unordered collection of unique items.
Upvotes: 15
Reputation: 137336
Use dict.fromkeys
:
>>> my_list = [1, 2, 3]
>>> dict.fromkeys(my_list)
{1: None, 2: None, 3: None}
Values default to None
, but you can specify them as an optional argument:
>>> my_list = [1, 2, 3]
>>> dict.fromkeys(my_list, 0)
{1: 0, 2: 0, 3: 0}
From the docs:
a.fromkeys(seq[, value]) Creates a new dictionary with keys from seq and values set to value.
dict.fromkeys is a class method that returns a new dictionary. value defaults to None. New in version 2.3.
Upvotes: 23