Python list of tuples to dictionary - python

In Python 2.7, suppose I have a list with 2 member sets like this
d = [(1, 'value1'), (2, 'value2'), (3, 'value3')]
What is the easiest way in python to turn it into a dictionary like this:
d = {1 : 'value1', 2 : 'value2', 3 : 'value3'}
Or, the opposite, like this?
d = {'value1' : 1, 'value2': 2, 'value3' : 3}
Thanks

The dict constructor can take a sequence. so...
dict([(1, 'value1'), (2, 'value2'), (3, 'value3')])
and the reverse is best done with a dictionary comprehension
{k: v for v,k in [(1, 'value1'), (2, 'value2'), (3, 'value3')]}

If your list is in the form of a list of tuples then you can simply use dict().
In [5]: dict([(1, 'value1'), (2, 'value2'), (3, 'value3')])
Out[5]: {1: 'value1', 2: 'value2', 3: 'value3'}
A dictionary comprehension can be used to construct the reversed dictionary:
In [13]: { v : k for (k,v) in [(1, 'value1'), (2, 'value2'), (3, 'value3')] }
Out[13]: {'value1': 1, 'value2': 2, 'value3': 3}

>>> lis = [(1, 'value1'), (2, 'value2'), (3, 'value3')]
Use dict() for the first one:
>>> dict(lis)
{1: 'value1', 2: 'value2', 3: 'value3'}
And a dict comprehension for the second one:
>>> {v:k for k,v in lis}
{'value3': 3, 'value2': 2, 'value1': 1}
dict() converts an iterable into a dict:
>>> print dict.__doc__
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)

lst = [(1, 'value1'), (2, 'value2'), (3, 'value3')]
To turn it to dict, just do
dict(lst)
to reverse it, you can do
dict((b,a) for a,b in lst)

dict(my_list) should probably do the trick. Also, I think you have a list of tuples, not sets.

>>> d = [(1, 'value1'), (2, 'value2'), (3, 'value3')]
>>> dict(d)
{1: 'value1', 2: 'value2', 3: 'value3'}
>>> dict(map(reversed, d))
{'value3': 3, 'value2': 2, 'value1': 1}

Related

Convert a list comprehension to functional programming

I have a list of dictionaries
lst = [{'a': (1, 2, 3), 'b': (2, 3)},
{'c': (3, 6), 'd': (4, 8), 'e': (5, 10)},
{'d': (6, 12), 'e': (7, 14)}]
For each key in each dictionary, I want to keep only the first element of the values. So the desired output is
[{'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5}, {'d': 6, 'e': 7}]
I can get it using a list comprehension like
[{key: val[0] for key, val in dct.items()} for dct in lst]
However, I want to know if it's possible to get the same output using map, itemgetter, itertools, functools etc. What I have so far:
map(dict.values, lst)
But I don't know how to go from here.
For nested iterations, I don't think we can do it without the help of lambda expressions:
from operator import itemgetter, methodcaller
list(map(
lambda items: dict(zip(
map(itemgetter(0), items),
map(itemgetter(0), map(itemgetter(1), items))
)), map(methodcaller('items'), lst)))
# [{'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5}, {'d': 6, 'e': 7}]
I have to say it's very ugly.
Update:
I found a way to avoid lambda:
First, according to the comment area, we simplify the above expression (the outermost list is omitted here to reduce the difficulty of understanding):
func = lambda d: dict(zip(d, map(itemgetter(0), d.values())))
map(func, lst)
It is easy to observe that dict can be moved outside lambda. We just need to add another map:
func = lambda d: zip(d, map(itemgetter(0), d.values()))
map(dict, map(func, lst))
Similarly, we can move the zip outside lambda:
func = lambda d: map(itemgetter(0), d.values())
map(dict, map(zip, lst, map(func, lst)))
This seems to be the end, and there seems to be no way to convert lambda into a combination of multiple built-in functions, but there are still ways, let's first try to move d.values outside lambda. Here, since the element type of the list is determined, we directly use dict.values instead of operator.methodcaller:
func = lambda values: map(itemgetter(0), values)
map(dict, map(zip, lst, map(func, map(dict.values, lst))))
The answer is ready to come out. We can eliminate lambda by using functools.partial:
map(dict, map(zip, lst, map(partial(map, itemgetter(0)), map(dict.values, lst))))
Test:
>>> from operator import itemgetter
>>> from functools import partial
>>> lst = [{'a': (1, 2, 3), 'b': (2, 3)},
... {'c': (3, 6), 'd': (4, 8), 'e': (5, 10)},
... {'d': (6, 12), 'e': (7, 14)}]
>>> map(dict, map(zip, lst, map(partial(map, itemgetter(0)), map(dict.values, lst))))
<map object at 0x000002A0542CBB20>
>>> list(_)
[{'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5}, {'d': 6, 'e': 7}]

Eliminating duplicate valued key from a dict

I have the following dictionary,
>>> names
{1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
What is the best way to eliminate keys with duplicate entries based on the first entry in the value i.e 1 and 3 are duplicates because of 'c1' and 2 and 4 are duplicates because of 'c2'?
I would like the final output to be something like this
>>> uniqueNames
{1: ('c1', 1), 2: ('c2', 2) }
Similar to how you would eliminate duplicates in a regular list while keeping the list's order.
The only real difference here is that dictionaries have no order, which means that iteration order through names.items is arbitrary so you will keep an arbitrary key-value pair with a unique first item for the value-tuple.
>>> names = {1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
>>>
>>> seen = set()
>>> unique_names = {}
>>>
>>> for k, (v0, v1) in names.items():
... if v0 not in seen:
... unique_names[k] = (v0, v1)
... seen.add(v0)
...
>>> unique_names
{1: ('c1', 1), 2: ('c2', 2)}
Here is the cryptic one-liner such questions tend to elicit:
unique_names = dict({i[1][0]: i for i in names.items()}.values())
If you want to guarantee to keep the smallest key:
unique_names = dict({i[1][0]: i for i in sorted(names.items(), reverse=True)}.values())
Collects the old items as values to the keys to be uniquified and builds a new dict from the items that remain as values in said dict.
Try:
ulist = [] # unique-list
outdict = {} # dict for output
for i in names.items(): # i will be as: (1, ('c1', 1))
if i[1][0] not in ulist:
ulist.append(i[1][0]) # add unique item to unique-list
outdict[i[0]] = i[1] # add entry to output dict
print(outdict)
Output:
{1: ('c1', 1), 2: ('c2', 2)}
You could solve it like this:
names = {1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
values_set = set()
unique_names = {}
for key, value in names.items():
if value[0] not in values_set:
values_set.add(value[0])
unique_names[key] = value
print(unique_names)
Do a set of first tuple values and then knowing what values are unique you can pop keys from the dict.
>>> temp = {1: ('a', '1'), 2: ('b', '2'), 3: ('a', '3'), 4: ('b', '4')}
>>> uniques = set()
>>> uniquedict = {}
>>> for key, value in temp.iteritems():
... if value[0] not in uniques:
... uniques.update(value[0])
... uniquedict[key]=value
...
>>>
>>> uniquedict
{1: ('a', '1'), 2: ('b', '2')}
edit: this is for python 2.7, #mrCarnivore answer is for python 3
You could use collections.defaultdict to group what you want, and only take the first value:
from collections import defaultdict
d = {1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
groups = defaultdict(list)
for num1, (entry, num2) in d.items():
groups[entry].append((num1, num2))
# defaultdict(<class 'list'>, {'c1': [(1, 1), (3, 3)], 'c2': [(2, 2), (4, 4)]})
result = {v[0][0]:(k, v[0][1]) for k, v in groups.items()}
print(result)
# {1: ('c1', 1), 2: ('c2', 2)}
Or even with itertools.groupby:
grouped = [list(g) for _, g in groupby(sorted(d.items(), key = lambda x: x[1][0]), key = lambda x: x[1][0])]
# [[(1, ('c1', 1)), (3, ('c1', 3))], [(2, ('c2', 2)), (4, ('c2', 4))]]
result = {k: v for (k, v) in [x[0] for x in grouped]}
print(result)
# {1: ('c1', 1), 2: ('c2', 2)}

Can I save dictionaries as lists? [duplicate]

If I have a dictionary like:
{'a': 1, 'b': 2, 'c': 3}
How can I convert it to this?
[('a', 1), ('b', 2), ('c', 3)]
And how can I convert it to this?
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> list(d.items())
[('a', 1), ('c', 3), ('b', 2)]
For Python 3.6 and later, the order of the list is what you would expect.
In Python 2, you don't need list.
since no one else did, I'll add py3k versions:
>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> list(d.items())
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v, k) for k, v in d.items()]
[(1, 'a'), (3, 'c'), (2, 'b')]
You can use list comprehensions.
[(k,v) for k,v in a.iteritems()]
will get you [ ('a', 1), ('b', 2), ('c', 3) ] and
[(v,k) for k,v in a.iteritems()]
the other example.
Read more about list comprehensions if you like, it's very interesting what you can do with them.
Create a list of namedtuples
It can often be very handy to use namedtuple. For example, you have a dictionary of 'name' as keys and 'score' as values like:
d = {'John':5, 'Alex':10, 'Richard': 7}
You can list the items as tuples, sorted if you like, and get the name and score of, let's say the player with the highest score (index=0) very Pythonically like this:
>>> player = best[0]
>>> player.name
'Alex'
>>> player.score
10
How to do this:
list in random order or keeping order of collections.OrderedDict:
import collections
Player = collections.namedtuple('Player', 'name score')
players = list(Player(*item) for item in d.items())
in order, sorted by value ('score'):
import collections
Player = collections.namedtuple('Player', 'score name')
sorted with lowest score first:
worst = sorted(Player(v,k) for (k,v) in d.items())
sorted with highest score first:
best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)
[(k,v) for (k,v) in d.iteritems()]
and
[(v,k) for (k,v) in d.iteritems()]
What you want is dict's items() and iteritems() methods. items returns a list of (key,value) tuples. Since tuples are immutable, they can't be reversed. Thus, you have to iterate the items and create new tuples to get the reversed (value,key) tuples. For iteration, iteritems is preferable since it uses a generator to produce the (key,value) tuples rather than having to keep the entire list in memory.
Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = { 'a': 1, 'b': 2, 'c': 3 }
>>> a.items()
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v,k) for (k,v) in a.iteritems()]
[(1, 'a'), (3, 'c'), (2, 'b')]
>>>
These are the breaking changes from Python 3.x and Python 2.x
For Python3.x use
dictlist = []
for key, value in dict.items():
temp = [key,value]
dictlist.append(temp)
For Python 2.7 use
dictlist = []
for key, value in dict.iteritems():
temp = [key,value]
dictlist.append(temp)
>>> a={ 'a': 1, 'b': 2, 'c': 3 }
>>> [(x,a[x]) for x in a.keys() ]
[('a', 1), ('c', 3), ('b', 2)]
>>> [(a[x],x) for x in a.keys() ]
[(1, 'a'), (3, 'c'), (2, 'b')]
By keys() and values() methods of dictionary and zip.
zip will return a list of tuples which acts like an ordered dictionary.
Demo:
>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> zip(d.keys(), d.values())
[('a', 1), ('c', 3), ('b', 2)]
>>> zip(d.values(), d.keys())
[(1, 'a'), (3, 'c'), (2, 'b')]
A alternative one would be
list(dictionary.items()) # list of (key, value) tuples
list(zip(dictionary.values(), dictionary.keys())) # list of (value, key) tuples
d = {'John':5, 'Alex':10, 'Richard': 7}
list = []
for i in d:
k = (i,d[i])
list.append(k)
print list
Python3 dict.values() not return a list. This is the example
mydict = {
"a": {"a1": 1, "a2": 2},
"b": {"b1": 11, "b2": 22}
}
print(mydict.values())
> output: dict_values([{'a1': 1, 'a2': 2}, {'b1': 11, 'b2': 22}])
print(type(mydict.values()))
> output: <class 'dict_values'>
print(list(mydict.values()))
> output: [{'a1': 1, 'a2': 2}, {'b1': 11, 'b2': 22}]
print(type(list(mydict.values())))
> output: <class 'list'>
x = {'a': 1, 'b': 2, 'c': 4, 'd':3}
sorted(map(lambda x : (x[1],x[0]),x.items()),key=lambda x : x[0])
Lets break the above code into steps
step1 = map(lambda x : (x[1],x[0]),x.items())
x[1] : Value
x[0] : Key
Step1 will create a list of tuples containing pairs in the form of (value,key) e.g. (4,'c')
step2 = sorted(step1,key=lambda x : x[0])
Step2 take the input of from Step 1 and sort using the 1st value of the tuple

How to sum list of tuples?

I have a list of tuples:
[ (a,1), (a,2), (b,1), (b,3) ]
I want to get the sum of both the a and b values. The results should be in this format:
[ { 'key' : a, 'value' : 3 }, {'key' : b, 'value' : 4 } ]
How can I do this?
from itertools import groupby
[{'key': k, 'value': sum(v for _,v in g)} for k, g in groupby(sorted(lst), key = lambda x: x[0])]
# [{'key': 'a', 'value': 3}, {'key': 'b', 'value': 4}]
from collections import defaultdict
lst = [("a", 1), ("a", 2), ("b", 1), ("b", 3)]
out = defaultdict(list)
[out[v[0]].append(v[1]) for v in lst]
out = [{"key": k, "value": sum(v)} for k, v in out.iteritems()]
print out
You can use collections.Counter to create a multiset from the initial list and then modify the result to match your case:
from collections import Counter
lst = [('a', 1), ('a', 2), ('b', 1), ('b', 3)]
part = sum((Counter({i[0]: i[1]}) for i in lst), Counter())
# Counter({'b': 4, 'a': 3})
final = [{'key': k, 'value': v} for k, v in part.items()]
# [{'key': 'b', 'value': 4}, {'key': 'a', 'value': 3}]
Very similar to answers given already. Little bit longer, but easier to read, IMHO.
from collections import defaultdict
lst = [('a', 1), ('a', 2), ('b', 1), ('b', 3)]
dd = defaultdict(int)
for name, value in lst:
dd[name] += value
final = [{'key': k, 'value': v} for k, v in dd.items()]
(last line copied from Moses Koledoye's answer)
from collections import Counter
a = [('a', 1), ('a', 2), ('b', 1), ('b', 3)]
c = Counter()
for tup in a:
c = c + Counter(dict([tup]))

How can I convert a dictionary into a list of tuples?

If I have a dictionary like:
{'a': 1, 'b': 2, 'c': 3}
How can I convert it to this?
[('a', 1), ('b', 2), ('c', 3)]
And how can I convert it to this?
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> list(d.items())
[('a', 1), ('c', 3), ('b', 2)]
For Python 3.6 and later, the order of the list is what you would expect.
In Python 2, you don't need list.
since no one else did, I'll add py3k versions:
>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> list(d.items())
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v, k) for k, v in d.items()]
[(1, 'a'), (3, 'c'), (2, 'b')]
You can use list comprehensions.
[(k,v) for k,v in a.iteritems()]
will get you [ ('a', 1), ('b', 2), ('c', 3) ] and
[(v,k) for k,v in a.iteritems()]
the other example.
Read more about list comprehensions if you like, it's very interesting what you can do with them.
Create a list of namedtuples
It can often be very handy to use namedtuple. For example, you have a dictionary of 'name' as keys and 'score' as values like:
d = {'John':5, 'Alex':10, 'Richard': 7}
You can list the items as tuples, sorted if you like, and get the name and score of, let's say the player with the highest score (index=0) very Pythonically like this:
>>> player = best[0]
>>> player.name
'Alex'
>>> player.score
10
How to do this:
list in random order or keeping order of collections.OrderedDict:
import collections
Player = collections.namedtuple('Player', 'name score')
players = list(Player(*item) for item in d.items())
in order, sorted by value ('score'):
import collections
Player = collections.namedtuple('Player', 'score name')
sorted with lowest score first:
worst = sorted(Player(v,k) for (k,v) in d.items())
sorted with highest score first:
best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)
[(k,v) for (k,v) in d.iteritems()]
and
[(v,k) for (k,v) in d.iteritems()]
What you want is dict's items() and iteritems() methods. items returns a list of (key,value) tuples. Since tuples are immutable, they can't be reversed. Thus, you have to iterate the items and create new tuples to get the reversed (value,key) tuples. For iteration, iteritems is preferable since it uses a generator to produce the (key,value) tuples rather than having to keep the entire list in memory.
Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = { 'a': 1, 'b': 2, 'c': 3 }
>>> a.items()
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v,k) for (k,v) in a.iteritems()]
[(1, 'a'), (3, 'c'), (2, 'b')]
>>>
These are the breaking changes from Python 3.x and Python 2.x
For Python3.x use
dictlist = []
for key, value in dict.items():
temp = [key,value]
dictlist.append(temp)
For Python 2.7 use
dictlist = []
for key, value in dict.iteritems():
temp = [key,value]
dictlist.append(temp)
>>> a={ 'a': 1, 'b': 2, 'c': 3 }
>>> [(x,a[x]) for x in a.keys() ]
[('a', 1), ('c', 3), ('b', 2)]
>>> [(a[x],x) for x in a.keys() ]
[(1, 'a'), (3, 'c'), (2, 'b')]
By keys() and values() methods of dictionary and zip.
zip will return a list of tuples which acts like an ordered dictionary.
Demo:
>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> zip(d.keys(), d.values())
[('a', 1), ('c', 3), ('b', 2)]
>>> zip(d.values(), d.keys())
[(1, 'a'), (3, 'c'), (2, 'b')]
A alternative one would be
list(dictionary.items()) # list of (key, value) tuples
list(zip(dictionary.values(), dictionary.keys())) # list of (value, key) tuples
d = {'John':5, 'Alex':10, 'Richard': 7}
list = []
for i in d:
k = (i,d[i])
list.append(k)
print list
Python3 dict.values() not return a list. This is the example
mydict = {
"a": {"a1": 1, "a2": 2},
"b": {"b1": 11, "b2": 22}
}
print(mydict.values())
> output: dict_values([{'a1': 1, 'a2': 2}, {'b1': 11, 'b2': 22}])
print(type(mydict.values()))
> output: <class 'dict_values'>
print(list(mydict.values()))
> output: [{'a1': 1, 'a2': 2}, {'b1': 11, 'b2': 22}]
print(type(list(mydict.values())))
> output: <class 'list'>
x = {'a': 1, 'b': 2, 'c': 4, 'd':3}
sorted(map(lambda x : (x[1],x[0]),x.items()),key=lambda x : x[0])
Lets break the above code into steps
step1 = map(lambda x : (x[1],x[0]),x.items())
x[1] : Value
x[0] : Key
Step1 will create a list of tuples containing pairs in the form of (value,key) e.g. (4,'c')
step2 = sorted(step1,key=lambda x : x[0])
Step2 take the input of from Step 1 and sort using the 1st value of the tuple

Categories