List of tuples to dictionary [duplicate] - python

This question already has answers here:
How to convert list of key-value tuples into dictionary?
(7 answers)
Closed 2 years ago.
Here's how I'm currently converting a list of tuples to dictionary in Python:
l = [('a',1),('b',2)]
h = {}
[h.update({k:v}) for k,v in l]
> [None, None]
h
> {'a': 1, 'b': 2}
Is there a better way? It seems like there should be a one-liner to do this.

Just call dict() on the list of tuples directly
>>> my_list = [('a', 1), ('b', 2)]
>>> dict(my_list)
{'a': 1, 'b': 2}

It seems everyone here assumes the list of tuples have one to one mapping between key and values (e.g. it does not have duplicated keys for the dictionary). As this is the first question coming up searching on this topic, I post an answer for a more general case where we have to deal with duplicates:
mylist = [(a,1),(a,2),(b,3)]
result = {}
for i in mylist:
result.setdefault(i[0],[]).append(i[1])
print(result)
>>> result = {a:[1,2], b:[3]}

The dict constructor accepts input exactly as you have it (key/value tuples).
>>> l = [('a',1),('b',2)]
>>> d = dict(l)
>>> d
{'a': 1, 'b': 2}
From the documentation:
For example, these all return a
dictionary equal to {"one": 1, "two":
2}:
dict(one=1, two=2)
dict({'one': 1, 'two': 2})
dict(zip(('one', 'two'), (1, 2)))
dict([['two', 2], ['one', 1]])

With dict comprehension:
h = {k:v for k,v in l}

Functional decision for #pegah answer:
from itertools import groupby
mylist = [('a', 1), ('b', 3), ('a', 2), ('b', 4)]
#mylist = iter([('a', 1), ('b', 3), ('a', 2), ('b', 4)])
result = { k : [*map(lambda v: v[1], values)]
for k, values in groupby(sorted(mylist, key=lambda x: x[0]), lambda x: x[0])
}
print(result)
# {'a': [1, 2], 'b': [3, 4]}

Related

How to get value from dictionary in list of tuples?

I have a dictionary like below and I want to store the values meaning 1, 1 in a list.
sc_dict=[('n', {'rh': 1}), ('n', {'rhe': 1}), ('nc', {'rhex': 1})]
I want an array [1,1,1].
This is my code:
dict_part = [sc[1] for sc in sc_dict]
print(dict_part[1])
L1=[year for (title, year) in (sorted(dict_part.items(), key=lambda t: t[0]))]
print(L1)
>>> [v for t1, t2 in sc_dict for k, v in t2.items()]
[1, 1, 1]
t1 and t2 being respectively the first and second item of each tuple, and k, v the key-value pairs in the dict t2.
You can use unpacking:
sc_dict=[('n', {'rh': 1}), ('n', {'rhe': 1}), ('nc', {'rhex': 1})]
new_data = [list(b.values())[0] for _, b in sc_dict]
Output:
[1, 1, 1]
It can become slightly cleaner with one additional step:
d = [(a, b.items()) for a, b in sc_dict]
new_data = [i for _, [(c, i)] in d]
You can use next to retrieve the first value of your dictionary as part of a list comprehension.
This works since your dictionaries have length 1.
sc_dict=[('n', {'rh': 1}), ('n', {'rhe': 1}), ('nc', {'rhex': 1})]
res = [next(iter(i[1].values())) for i in sc_dict]
# [1, 1, 1]
I tried the simple way like below:
sc_dict=[('n', {'rh': 1}), ('n', {'rhe': 1}), ('nc', {'rhex': 1})]
l = []
for i in range(len(sc_dict)):
l.extend(sc_dict[i][1].values())
print l
The output l would be [1, 1, 1]

Python tuples dictionary addition

I have a dictionary of tuples as follows:
tupledict = {('A','B','C'):2, ('A',): 3, ('B',) :4, ('C',): 5}
Currently, the first tuple is 2, however I want it to read values from the individual tuples to give me the correct sum of 12.
So output should be:
tupledict = {('A','B','C'):12, ('A',): 3, ('B',) :4, ('C',): 5}
How could this be done?
You can use a dictionary comprehension to build a new dict:
>>> tupledict = {('A','B','C'): 2, ('A',): 3, ('B',): 4, ('C',): 5}
>>> {t: sum(tupledict.get((x,), 0) for x in t) for t in tupledict}
{('A', 'B', 'C'): 12, ('A',): 3, ('B',): 4, ('C',): 5}
Using tupledict.get() instead of indexing handles the case when some 1-tuple is missing.
You can do this as follows:
for key in list(tupledict):
if len(key) > 1:
tupledict[key] = sum(tupledict.get((subk,),0) for subk in key)
So we iterate over the list of keys (we use a list(..) such that we do not update a collection we are currently iterating over.
In case the len(key) is greater than 1, we calculate the sum of the subkeys, and assign that value to the tupledict.
This constructs the following dictionary:
>>> tupledict = {('A','B','C'):2, ('A',): 3, ('B',) :4, ('C',): 5}
>>> for key in list(tupledict):
... if len(key) > 1:
... tupledict[key] = sum(tupledict.get((subk,),0) for subk in key)
...
>>> tupledict
{('A',): 3, ('B',): 4, ('C',): 5, ('A', 'B', 'C'): 12}
Alternatively, you can subclass the dictionary and override the __getitem__ such that if one requests a tuple with length greater than 1, it adds the elements together. In this case we will save on memory (and do not have to updated all tuples) since the tuples ('A','B','C') are stored implicitly:
class SumDict(dict):
def __getitem__(self, key):
if len(key) > 1:
return sum(self.get((subk,) ,0) for subk in key)
else:
return super().__getitem__(key)
For example:
>>> tupledict = {('A',): 3, ('B',) :4, ('C',): 5}
>>> sd = SumDict(tupledict)
>>> sd[('A','B','C')]
12
>>> sd[('A','B')]
7

How to add list to dictionary by sequentially? [duplicate]

This question already has answers here:
How to keep keys/values in same order as declared?
(13 answers)
Closed 6 years ago.
Example dictionary:
dictionary = {}
dictionary['a'] = 1
dictionary['b'] = 2
dictionary['c'] = 3
dictionary['d'] = 4
dictionary['e'] = 5
print(dictionary)
run this code 1st time:
{'c': 3, 'd': 4, 'e': 5, 'a': 1, 'b': 2}
2nd:
{'e': 5, 'a': 1, 'b': 2, 'd': 4, 'c': 3}
3rd:
{'d': 4, 'a': 1, 'b': 2, 'e': 5, 'c': 3}
My expected result:
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
or if my code is:
dictionary = {}
dictionary['r'] = 150
dictionary['j'] = 240
dictionary['k'] = 98
dictionary['l'] = 42
dictionary['m'] = 57
print(dictionary)
#The result should be
{'r': 150, 'j': 240, 'k': 98, 'l': 42, 'm': 57}
Because of my project the dictionary with 100++ lists will write to a file and it will easier to read.
P.S. sorry for my english and if my question title is not clear.
Thank you.
Python's dict are unordered in nature. For maintaining the order in which elements are inserted, use collection.OrderedDict().
Sample Run:
>>> from collections import OrderedDict
>>> dictionary = OrderedDict()
>>> dictionary['a'] = 1
>>> dictionary['b'] = 2
>>> dictionary['c'] = 3
>>> dictionary['d'] = 4
>>> dictionary['e'] = 5
# first print
>>> print(dictionary)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)])
# second print, same result
>>> print(dictionary)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)])
For writing it to the json file, you can dump the dict object to string using json.dumps() as:
>>> import json
>>> json.dumps(dictionary) # returns JSON string
'{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}'
As per the collections.OrderedDict() document:
Return an instance of a dict subclass, supporting the usual dict methods. An OrderedDict is a dict that remembers the order that keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting an entry and reinserting it will move it to the end.
Read up on OrderedDict.
https://docs.python.org/2/library/collections.html#collections.OrderedDict
It remembers the insertion order of the keys.

Taking the max from multiple Counters instead of adding them up - Python

How else to "combine" multiple Counter but only taking the maximum value for each key for the "combined" Counter?
Given a couple of Counters as such:
>>> from collections import Counter
>>> x = Counter([('a'), ('a', 'bc'), ('a', 'bc'), ('xyz', 'hooli')])
>>> y = Counter([('a'), ('a'), ('a'), ('asd', 'asd')])
I could do this to add them up:
>>> x + y
Counter({'a': 4, ('a', 'bc'): 2, ('asd', 'asd'): 1, ('xyz', 'hooli'): 1})
But if my aim is to get combine the Counters but if they have the same key, the goal is NOT to add the values up but instead take the max of it. How do I do so?
I've tried the following code:
>>> z = Counter()
>>> for c in [x,y]:
... for k in c:
... z[k] = max(z.get(k,0), c[k])
...
>>> z
Counter({'a': 3, ('a', 'bc'): 2, ('asd', 'asd'): 1, ('xyz', 'hooli'): 1})
But is there other way to achieve the same output?
The Counter union operator (|) returns the maximum counts:
>>> x | y
Counter({'a': 3, ('a', 'bc'): 2, ('xyz', 'hooli'): 1, ('asd', 'asd'): 1})

Python Sorted by Index

Lets say there is a dictionary
foo = {'b': 1, 'c':2, 'a':3 }
I want to iterate over this dictionary in the order of the appearance of items in the dictionary.
for k,v in foo.items():
print k, v
prints
a 3
c 2
b 1
If we use sorted() function:
for k,v in sorted(foo.items()):
print k, v
prints
a 3
b 1
c 2
But i need them in the order in which they appear in the dictionary i;e
b 1
c 2
a 3
How do i achieve this ?
Dictionaries have no order. If you want to do that, you need to find some method of sorting in your original list. Or, save the keys in a list in the order they are saved and then access the dictionary using those as keys.
From The Python Docs
It is best to think of a dictionary as an unordered set of key: value
pairs, with the requirement that the keys are unique (within one
dictionary).
Example -
>>> testList = ['a', 'c', 'b']
>>> testDict = {'a' : 1, 'c' : 2, 'b' : 3}
>>> for elem in testList:
print elem, testDict[elem]
a 1
c 2
b 3
Or better yet, use an OrderedDict -
>>> from collections import OrderedDict
>>> testDict = OrderedDict([('a', 1), ('c', 2), ('b', 3)])
>>> for key, value in testDict.items():
print key, value
a 1
c 2
b 3
Maybe this?
sorted(foo, key=foo.get)
If you want to use your OrderedDict multiple times, use an OrderedDict like people have said. :) If you just want a one-liner for a one-off, change your sort function:
sorted(foo.items(), lambda a,b:a[1]-b[1])
You can do this by one-liner:
>>> sorted(foo.items(), key=lambda x: x[1])
[('b', 1), ('c', 2), ('a', 3)]
An ordered dictionary would have to be used to remember the order that they were stored in
>>>from collections import OrderedDict
>>>od = OrderedDict()
>>>od['b'] = 1
>>>od['c'] = 2
>>>od['a'] = 3
>>>print od
OrderedDict([('b',1), ('c',2), ('a',3)]
The see this more directly, the order you used to create the dict is not the order of the dict. The order is indeterminate.
>>> {'b': 1, 'c':2, 'a':3 }
{'a': 3, 'c': 2, 'b': 1}
If you just want to sort them by the keys do:
sorted_by_keys_dict = dict((y,x) for x,y in foo.iteritems())
for k,v in sorted(sorted_by_keys_dict.items()):
print v, k
a 1
c 2
b 3
or simply:
for k,v in sorted(dict((y,x) for x,y in foo.iteritems()).items()):
print v, k
a 1
c 2
b 3

Categories