Elegant way of temporarily assigning a variable within dictionary comprehension?
-
21-12-2019 - |
Question
Out of curiosity is it possible to write the following logic as a nice dict comprehension?
a = "a c\nb c\nn q\n".split('\n')[:-1]
output = {}
for line in a:
tmp = line.split(' ')
output[tmp[0]] = tmp[1]
I wrote the following, but without a temporary assignment I have to split twice which is unfortunate:
{line.split(' ')[0]:line.split(' ')[1] for line in a}
Is something more elegant possible?
Solution
Use a nested list comprehension:
{p[0]:p[1] for p in [l.split(" ") for l in a]}
Output:
{'a': 'c', 'b': 'c', 'n': 'q'}
OTHER TIPS
In this case, I think the dict constructor is a little nicer since it will take an iterable of 2-sequences:
dict(line.split() for line in a)
Demo:
>>> a
['a c', 'b c', 'n q']
>>> dict(line.split() for line in a)
{'a': 'c', 'b': 'c', 'n': 'q'}
Highly specific to the whitespace in your particular input:
>>> a = "a c\nb c\nn q\n".split('\n')[:-1]
>>> {line[0]:line[2] for line in a}
{'a': 'c', 'b': 'c', 'n': 'q'}
does that work:
>>> a = "a c\nb c\nn q\n".split('\n')[:-1]
>>> {i[0]:i[1] for line in a for i in [line.split(' ')]}
{'a': 'c', 'b': 'c', 'n': 'q'}
In this case, you can use
dict(line.split(' ') for line in a)
but for more complicated "value processing" I usually find it easier to use either "normal" loop (like you did) or write small helper function:
def helper(val):
...
return key, value
dict(helper(line) for line in a)
This is one thing (crippled lambda/anonymous function syntax) I really hate about python.
Use a nested list comprehension without a split.
>>> {line[0]:line[-1] for line in a}
{'a': 'c', 'b': 'c', 'n': 'q'}
Through python's re module,
>>> import re
>>> a = "a c\nb c\nn q\n"
>>> a
'a c\nb c\nn q\n'
>>> m = re.findall(r'^(.) (.)$', a, re.M)
>>> m
[('a', 'c'), ('b', 'c'), ('n', 'q')]
>>> dict(m)
{'a': 'c', 'b': 'c', 'n': 'q'}