I want to know if there's a more Pythonic way of doing the following, perhaps using dictionary comprehensions:
A = some list
D = {}
for i,v in enumerate(A):
if v in D:
D[v].append(i)
else:
D[v] = [i]
Method 1: Using dict() method Using dict() method we can convert list comprehension to the dictionary. Here we will pass the list_comprehension like a list of tuple values such that the first value act as a key in the dictionary and the second value act as the value in the dictionary.
keys() function to make your code more explicit. To get a list of the dictionary's values, you can call the dict. values() function.
It definitely can have a list and any object as value but the dictionary cannot have a list as key because the list is mutable data structure and keys cannot be mutable else of what use are they.
List comprehensions are constructed from brackets containing an expression, which is followed by a for clause, that is [item-expression for item in iterator] or [x for x in iterator], and can then be followed by further for or if clauses: [item-expression for item in iterator if conditional].
Using defaultdict
:
from collections import defaultdict
D = defaultdict(list)
[D[v].append(i) for i, v in enumerate(A)]
Using setdefault
:
D = {}
[D.setdefault(v, []).append(i) for i, v in enumerate(A)]
I can't figure any mean to use a dictionnary comprehension without sorting the data:
from itertools import groupby
from operator import itemgetter
{v: ids for v, ids in groupby(enumerate(sorted(A)), itemgetter(1))}
Performances:
from collections import defaultdict
from itertools import groupby
from operator import itemgetter
from random import randint
A = tuple(randint(0, 100) for _ in range(1000))
def one():
D = defaultdict(list)
[D[v].append(i) for i, v in enumerate(A)]
def two():
D = {}
[D.setdefault(v, []).append(i) for i, v in enumerate(A)]
def three():
{v: ids for v, ids in groupby(enumerate(sorted(A)), itemgetter(1))}
from timeit import timeit
for func in (one, two, three):
print(func.__name__ + ':', timeit(func, number=1000))
Results (as always, the simplest win):
one: 0.25547646999984863
two: 0.3754340969971963
three: 0.5032370890003222
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With