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}]
Related
Have a list of dictionaries, something like this:
l = [{'a':25}, {'a':25}, {'b':30}, {'c':200}, {'b':30}]
want to find the distinct elements and their corresponding indices, something like this:
[
({'a':25}, [0,1]),
({'b':30}, [2,4]),
({'c':200}, [3]),
]
tried with itertools.groupby, but couldn't make it happen, perhaps I'm missing something, any other directions are great too.
Consider this list of dictionaries:
>>> dicts
[{'a': 3},
{'d': 4, 'a': 3, 'c': 1},
{'d': 8, 'c': 0, 'b': 9},
{'c': 3, 'a': 9},
{'a': 5, 'd': 8},
{'d': 5, 'b': 5, 'a': 0},
{'b': 7, 'c': 7},
{'d': 6, 'b': 7, 'a': 6},
{'a': 4, 'c': 1, 'd': 5, 'b': 2},
{'d': 7}]
Assuming you want all indices of every instance of every dictionary's keys:
idxs = {}
for i, d in enumerate(l):
for pair in d.items():
idxs.setdefault(pair, []).append(i)
This produces what I would consider more useful output, as it allows you to look up the indices of any specific key-value pair:
{('a', 3): [0, 1],
('d', 4): [1],
('c', 1): [1, 8],
('d', 8): [2, 4],
('c', 0): [2],
('b', 9): [2],
('c', 3): [3],
('a', 9): [3],
('a', 5): [4],
('d', 5): [5, 8],
('b', 5): [5],
('a', 0): [5],
('b', 7): [6, 7],
('c', 7): [6],
('d', 6): [7],
('a', 6): [7],
('a', 4): [8],
('b', 2): [8],
('d', 7): [9]}
However, if you must convert to List[Tuple[Dict[str, int], List[int]]], you can produce it very easily from the previous output:
>>> [(dict((p,)), l) for p, l in idxs.items()]
[({'a': 3}, [0, 1]),
({'d': 4}, [1]),
({'c': 1}, [1, 8]),
({'d': 8}, [2, 4]),
({'c': 0}, [2]),
({'b': 9}, [2]),
({'c': 3}, [3]),
({'a': 9}, [3]),
({'a': 5}, [4]),
({'d': 5}, [5, 8]),
({'b': 5}, [5]),
({'a': 0}, [5]),
({'b': 7}, [6, 7]),
({'c': 7}, [6]),
({'d': 6}, [7]),
({'a': 6}, [7]),
({'a': 4}, [8]),
({'b': 2}, [8]),
({'d': 7}, [9])]
Turn the dictionaries into tuples so you can use them as keys in a dictionary. Then iterate over the list, adding the indexes to this dictionary.
locations_dict = {}
for i, d in enumerate(l):
dtuple = tuple(d.items())
locations_dict.setdefault(dtuple, []).append(i)
locations = [(dict(key), value) for key, value in locations_dict.items()]
from collections import defaultdict
indices = defaultdict(list)
for idx, val in enumerate(l):
indices[tuple(*val.items())].append(idx)
print(indices)
# output
defaultdict(list, {('a', 25): [0, 1], ('b', 30): [2, 4], ('c', 200): [3]})
Another way of doing it:
import ast
l = [{'a':25}, {'a':25}, {'b':30}, {'c':200}, {'b':30}]
n_dict = {}
for a, b in enumerate(l):
n_dict[str(b)] = n_dict.get(str(b), []) + [a]
print(list(zip( [ast.literal_eval(i) for i in n_dict.keys()], n_dict.values() )))
great idea with the dicts/defaultdicts, this also seems to work:
l = [{'a':25}, {'a':25}, {'b':30}, {'c':200}, {'b':30}, {'a': 25}]
sorted_values = sorted(enumerate(l), key=lambda x: str(x[1]))
grouped = itertools.groupby(sorted_values, lambda x: x[1])
grouped_indices = [(k, [x[0] for x in g]) for k, g in grouped]
print(grouped_indices)
the idea is that once an array is sorted (keeping the original indices as additional details) itertools/linux groupby is preaty similar to sql/pandas groupby
I have a dictionary
d_1 = { 'b':2, 'c':3, 'd':6}
How can I create a list of dictionaries by taking the combinations of the elements of dictionary as dictionary? Ex:
combs = [{'b':2}, { 'c':3}, {'d':6}, {'b':2, 'c':3}, {'c':3, 'd':6}, {'b':2, 'd':6}, { 'b':2, 'c':3, 'd':6}]
Use the below loop, in simply get all the numbers from range: [1, 2, 3], then simply use itertools.combinations and extend to fit them in, also than get the dictionary not with tuple at the end:
ld_1 = [{k:v} for k,v in d_1.items()]
l = []
for i in range(1, len(ld_1) + 1):
l.extend(list(itertools.combinations(ld_1, i)))
print([i[0] for i in l])
Using combinations from itertools:
[{i:d_1[i] for i in x} for x in chain.from_iterable(combinations(d_1, r) for r in range(1,len(d_1)+1))]
If what you want is a powerset you need to include the empty dictionary, too:
[{i:d_1[i] for i in x} for x in chain.from_iterable(combinations(d_1, r) for r in range(len(d_1)+1))]
(see itertools recipes)
You can try this:
from itertools import chain, combinations
def powerset(iterable):
"""powerset([1,2,3]) --> (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"""
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(1, len(s) + 1))
d_1 = {'b': 2, 'c': 3, 'd': 6}
comb = list(map(dict, powerset(d_1.items())))
print(comb)
Output:
[{'b': 2}, {'c': 3}, {'d': 6}, {'b': 2, 'c': 3}, {'b': 2, 'd': 6}, {'c': 3, 'd': 6}, {'b': 2, 'c': 3, 'd': 6}]
The syntax of printing a normal dictionary is
{'a': 1, 'c': 3, 'b': 2}
Whereas
The syntax of printing a OrderedDict is
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
Is there any way where i can print/return the OrderedDict in the Normal Dictionary way??
Use a custom __str__ method in your own OrderedDict class ; in the custom method, you can build the string you want:
from collections import OrderedDict
class MyOrderedDict(OrderedDict):
def __str__(self):
return "{%s}" % ", ".join([repr(k)+": "+str(v) for k, v in self.iteritems()])
d = MyOrderedDict([('a', 1), ('b', 2), ('c', 3)])
The easy way:
from collections import OrderedDict
a = {'a': 1, 'c': 3, 'b': 2}
new_dict = dict(OrderedDict(a))
print(new_dict)
print(type(new_dict))
Output:
{'a': 1, 'c': 3, 'b': 2}
<type 'dict'>
The hard way:
You can also return the OrderedDict to a simple dict using groupby from itertools module like this way:
from collections import OrderedDict
from itertools import groupby
a = {'a': 1, 'c': 3, 'b': 2}
new_dict = {key:list(val)[0][1] for key, val in groupby(OrderedDict(a).items(), lambda x : x[0])}
print(new_dict)
print(type(new_dict))
Output:
{'c': 3, 'a': 1, 'b': 2`}
<type 'dict'>
Edit:
I see that there is some downvotes because they think that the output should be an ordered string. So, this is how do deal with it:
from collections import OrderedDict
a = {'a': 1, 'c': 3, 'b': 2}
new_dict = OrderedDict(a)
b = "{%s}" % ", ".join([str(key)+":"+str(val) for key, val in sorted(new_dict.iteritems())])
print(b)
print(type(b))
Output:
{'a':1, 'b':2, 'c':3}
<type 'str'>
To print OrderedDict in a dict-way you can act like this (of course, if the actual order of the items does not matter to print):
def some_function():
d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
od = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
return od
my_ordered_dict_variable = some_function()
print('My Ordered Dicdict:', dict(my_ordered_dict_variable))
This code will print:
{'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
I want to filter out last value in tuple in list of dictionaries. For example
X = [{'a': (123, 12445), 'b': (234, 34)}, {'a': (45666, 4), 'b': (3, 12)}]
to
Y = [{'a': 123, 'b': 234}, {'a': 45666, 'b': 3} ]
My attempt:
[{ j: i[j][0] } for j in i.keys() for i in result ]
But I get this:
[{'a': 123}, {'a': 45666}, {'b': 234}, {'b': 3}]
Any help?
Edit:
Dictionary comprehensions only work in Python 2.7+. Since you are on Python 2.6, you can use dict with a generator expression:
>>> X = [{'a': (123, 12445), 'b': (234, 34)}, {'a': (45666, 4), 'b': (3, 12)}]
>>> [dict((k, v[0]) for k,v in x.iteritems()) for x in X]
[{'b': 234, 'a': 123}, {'b': 3, 'a': 45666}]
>>>
I have found many threads for sorting by values like here but it doesn't seem to be working for me...
I have a dictionary of lists that have tuples. Each list has a different amount of tuples. I want to sort the dictionary by how many tuples each list contain.
>>>to_format
>>>{"one":[(1,3),(1,4)],"two":[(1,2),(1,2),(1,3)],"three":[(1,1)]}
>>>for key in some_sort(to_format):
print key,
>>>two one three
Is this possible?
>>> d = {"one": [(1,3),(1,4)], "two": [(1,2),(1,2),(1,3)], "three": [(1,1)]}
>>> for k in sorted(d, key=lambda k: len(d[k]), reverse=True):
print k,
two one three
Here is a universal solution that works on Python 2 & Python 3:
>>> print(' '.join(sorted(d, key=lambda k: len(d[k]), reverse=True)))
two one three
dict= {'a': [9,2,3,4,5], 'b': [1,2,3,4, 5, 6], 'c': [], 'd': [1,2,3,4], 'e': [1,2]}
dict_temp = {'a': 'hello', 'b': 'bye', 'c': '', 'd': 'aa', 'e': 'zz'}
def sort_by_values_len(dict):
dict_len= {key: len(value) for key, value in dict.items()}
import operator
sorted_key_list = sorted(dict_len.items(), key=operator.itemgetter(1), reverse=True)
sorted_dict = [{item[0]: dict[item [0]]} for item in sorted_key_list]
return sorted_dict
print (sort_by_values_len(dict))
output:
[{'b': [1, 2, 3, 4, 5, 6]}, {'a': [9, 2, 3, 4, 5]}, {'d': [1, 2, 3, 4]}, {'e': [1, 2]}, {'c': []}]