Reputation: 3221
I am trying to use a dictionary comprehension using a nested list. As long as the keys are unique, all works fine. However if there are multiples of the key present I would like to append the values to that key instead of overwriting the value. Is this possible using a comprehension?
seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
print {key: [val] for key, val in seq1} # Or dict(seq1)
>>> {1: [[1, 2, 3, 4]], 2: [[5, 6, 7]]}
print {key: [val] for key, val in seq2}
>>> {1: [[5, 6, 7]]} # First value is overwritten
# Desired output:
def index_reads(reads):
result = {}
for i in reads:
d = dict([i])
for key, val in d.iteritems():
if key in result:
result[key].append(val)
else:
result[key] = [val]
return result
print index_reads(seq1)
>>> {1: [[1, 2, 3, 4]], 2: [[5, 6, 7]]}
print index_reads(seq2)
>>> {1: [[1, 2, 3, 4], [5, 6, 7]]}
Sorry, I couldn't find a repeat of this question.
Upvotes: 1
Views: 480
Reputation: 8162
Yes,with defaultdict works also:
from collections import defaultdict
seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
d={key: [val] for key, val in seq1}
d = defaultdict(list)
for key, val in seq2:
d[key].append(val)
print d
Then:
[(1, [[1, 2, 3, 4], [5, 6, 7]])
Or if we delete seq1,
seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
d={key: [val] for key, val in seq2}
d = defaultdict(list)
for key, val in seq2:
d[key].append(val)
print d
Again you will have:
defaultdict(<type 'list'>, {1: [[1, 2, 3, 4], [5, 6, 7]]})
Upvotes: 0
Reputation: 21619
You could use groupby
from itertools
.
import itertools
import operator
seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
def index_reads(seq):
return {k: [i[1] for i in g] for k, g in itertools.groupby(seq, operator.itemgetter(0))}
print index_reads(seq1)
print index_reads(seq2)
Output
{1: [[1, 2, 3, 4]], 2: [[5, 6, 7]]}
{1: [[1, 2, 3, 4], [5, 6, 7]]}
Upvotes: 1
Reputation: 107347
You don't need list comprehension. As a more pythonic way you can use dict.setdefault()
method :
>>> d={key: [val] for key, val in seq1}
>>> for key, val in seq2:
... d.setdefault(key,[]).append(val)
...
>>> d
{1: [[1, 2, 3, 4], [1, 2, 3, 4], [5, 6, 7]], 2: [[5, 6, 7]]}
You can also use collections.defaultdict
for such tasks.
Also it shows its power when you have different keys in seq2
for example :
>>> seq2 = [[1, [1,2,3,4]], [5, [5,6,7]]]
>>> d={key: [val] for key, val in seq1}
>>> for key, val in seq2:
... d.setdefault(key,[]).append(val)
...
>>> d
{1: [[1, 2, 3, 4], [1, 2, 3, 4]], 2: [[5, 6, 7]], 5: [[5, 6, 7]]}
And if you don't want to keep duplicates you can use a defaultdict
with set
as container :
>>> from collections import defaultdict
>>> seq1 = [[1, [1,2,3,4]], [2, [5,6,7]]]
>>> seq2 = [[1, [1,2,3,4]], [1, [5,6,7]]]
>>>
>>> d=defaultdict(set)
>>> for key, val in seq1+seq2:
... d[key].add(tuple(val))
...
>>> d
defaultdict(<type 'set'>, {1: set([(5, 6, 7), (1, 2, 3, 4)]), 2: set([(5, 6, 7)])})
Upvotes: 2