Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary Comprehension for list values

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]
like image 832
lorenzocastillo Avatar asked Apr 11 '16 13:04

lorenzocastillo


People also ask

Can I use list comprehension with dictionary?

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.

How do I get a list of values in a 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.

Can dictionary have list as values?

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.

How do you use list comprehension in Python dictionary?

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


1 Answers

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
like image 149
aluriak Avatar answered Oct 19 '22 06:10

aluriak