Reputation: 137
I am using Python 3.6. I wrote following code, it's a for loop:
Edit: I made a mistake when I wrote var l down, so I re-type it here. Thanks for @Ender Look !!
l = [['a','1'], ['a','2'], ['a','3']]
d = {}
for i in l:
d[i[0]] = d.get(i[0], '') + '\t' + i[1]
print (d)
So, the result is what I want: {'a': '\t1\t2\t3'}
Then I refactor above code as comprehension:
dict2 = {}
dict2 = {i[0]: dict2.get(i[0], '') + '\t' + i[1] for i in l}
print(dict2)
I though they should return same output. But the dict2 is:
{'a': '\t3'}
I want to know what's the matter with my dict comprehension? Thanks a lot!
Upvotes: 3
Views: 218
Reputation: 11641
Yes, you can do it as a single dict comprehension.
{k: v
for d in [{}]
for k, v in [d.__setitem__(k, d.get(k, '') + '\t' + v) or d
for k, v in [['a','1'], ['a','2'], ['a','3']]][-1].items()}
You shouldn't.
Note how we had to create a reference to an inner dict d
anyway, since your algorithm has to look things up in the dict as it's being constructed. What is the outer comprehension even for? And we're throwing away all but the last element of the inner list comp.
It's much clearer to use a normal for loop like this,
d = {}
for k, v in [['a','1'], ['a','2'], ['a','3']]:
d[k] = d.get(k, '') + '\t' + v
Use the right tool for the job.
Upvotes: 0
Reputation: 26570
You don't necessarily need to use a comprehension here. You can make use of defaultdict
from collections:
>>> from collections import defaultdict
>>> d = defaultdict(str)
>>> for li in l:
... d[li[0]] += f'\t{li[1]}'
...
>>> d
defaultdict(<class 'str'>, {'a': '\t1\t2'})
Upvotes: 5
Reputation: 2391
Your dictionary comprehension doesn't work because it's use .get
on itself.
dict2 = {i[0]: dict2.get(i[0], '') + '\t' + i[1] for i in l}
Until the end of the whole dictionary comprehension, this new dictionary isn't assigned to your actual dict2
variable. So all the times your comprehension tries to retrieve the value from dict2.get(...)
it always executes that function from the empty dictionary dict2 = {}
.
Sadly, I don't know (and I don't think it exists) a way to use .get
on a dictionary comprehension about itself, because the variable dict2
isn't updated on "real time" (it wait until the end the comprehension). Or at least that I have understood, my humble knowledge isn't perfect.
Upvotes: 3