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': []}]
Related
I am trying to transform a dictionary of sets as the values with duplication to a dictionary with the unique sets as the value and at the same time join the keys together.
dic = {'a': {1, 2, 3}, 'b': {1, 2}, 'c': {1, 3, 2}, 'd': {1, 2, 3}}
Should be changed to
{'a-c-d': {1, 2, 3}, 'b': {1, 2}}
My try is as below, but I think there has to be a better way.
def transform_dictionary(dic: dict) -> dict:
dic = {k: frozenset(v) for k, v in dic.items()}
key_list = list(dic.keys())
value_list = list(dic.values())
dict_transformed = {}
for v_uinque in set(value_list):
sub_key_list = []
for i, v in enumerate(value_list):
if v == v_uinque:
sub_key_list.append(str(key_list[i]))
dict_transformed['-'.join(sub_key_list)] = set(v_uinque)
return dict_transformed
print(transform_dictionary(dic))
You can "invert" the input dictionary into a dictionary mapping frozensets into a set of keys.
import collections
dic = {'a': {1, 2, 3}, 'b': {1, 2}, 'c': {1, 3, 2}, 'd': {1, 2, 3}}
keys_per_set = collections.defaultdict(list)
for key, value in dic.items():
keys_per_set[frozenset(value)].append(key)
Then invert that dictionary mapping back into the desired form:
{'-'.join(keys): value for (value, keys) in keys_per_set.items()}
Output:
{'a-c-d': frozenset({1, 2, 3}), 'b': frozenset({1, 2})}
This will turn the values into a frozenset, but you could "thaw" them with a set(value) in the last list comprehension.
from itertools import groupby
dic_output = {'-'.join(v):g for g,v in groupby(sorted(dic_input,
key=dic_input.get),
key=lambda x: dic_input[x])}
Output
{'b': {1, 2}, 'a-c-d': {1, 2, 3}}
dict1 = {'a': 10, 'b': 8, 'c':5}
dict2 = {'d': 6, 'c': 4, 'a':20}
Given two dictionaries, I'd like an output of.
output = {'a':30, 'b':8, 'c':9, 'd':6}
This is what I've so far, not quite sure what I'd do next.
I'm looking for a solution that is efficient in time/space complexity.
def merge_dict(dict1, dict2):
merged_dictionaries = {**dict1, **dict2}
return merged_dictionaries
dict1 = {'a': 10, 'b': 8, 'c':5}
dict2 = {'d': 6, 'c': 4, 'a':20}
merge_dictionaries = merge_dict (dict1, dict2)
sorted_dictionary = sorted(merge_dictionaries)
If the values are numeric, you can use counters:
from collections import Counter
def merge_dicts(*dicts):
return dict(sum(map(Counter, dicts), Counter()))
dict1 = merge_dicts(dict1, dict2)
dict1
# {'a': 30, 'b': 8, 'c': 9, 'd': 6}
This might be a bit excessive for only two dictionaries, so another option is:
for k, v in dict2.items():
dict1[k] = dict1.setdefault(k, 0) + v
dict1
# {'a': 30, 'b': 8, 'c': 9, 'd': 6}
Which updates dict1 in-place.
Finally, if you really need the result sorted (python3.7+), use
result = {k : dict1[k] for k in sorted(dict1)}
You can use a dict comprehension that iterates over a sorted union of the keys of the two dicts, and outputs values that are sums of the respective values of two dicts by the given keys, defaulting to 0:
{k: dict1.get(k, 0) + dict2.get(k, 0) for k in sorted(dict1.keys() | dict2.keys())}
This returns:
{'a': 30, 'b': 8, 'c': 9, 'd': 6}
result = dict(Counter(dict1) + Counter(dict2))
result = {k: result[k] for k in sorted(result)}
First merge the dicts together by turning them into Counters and convert the result it back into a dict, then sort the dict by keys.
You can Try Collections for add two dictionary..
from collections import Counter
def merged_dic():
dict1 = {'a': 10, 'b': 8, 'c':5}
dict2 = {'d': 6, 'c': 4, 'a':20}
a = Counter(dict1)
b = Counter(dict2)
c = a+b
print(dict(c))
merged_dic()
Output:- {'a': 30, 'b': 8, 'c': 9, 'd': 6}
Assuming that there are two python list with the same structure like this:
var1 = [{'a':1,'b':2},{'c':2,'d':5,'h':4},{'c':2,'d':5,'e':4}]
var2 = [{'a':3,'b':2},{'c':1,'d':5,'h':4},{'c':5,'d':5,'e':4}]
In my case, i need to combine both of those list, so i'll get this value :
result = [{'a':4,'b':4},{'c':3,'d':10,'h':8},{'c':7,'d':10,'e':8}]
How can i do that?
zip-based one-liner comprehension:
result = [{k: d1[k]+d2[k] for k in d1} for d1, d2 in zip(var1, var2)]
This assumes that two dicts at the same index always have identical key sets.
Use list comprehensions to put the code in one line,
result = [{key : d1.get(key, 0)+d2.get(key, 0)
for key in set(d1.keys()) | set(d2.keys())} # union two sets
for d1, d2 in zip(var1, var2)]
print(result)
[{'a': 4, 'b': 4}, {'h': 8, 'c': 3, 'd': 10}, {'c': 7, 'e': 8, 'd': 10}]
This code takes into consideration the case that two dictionaries may not have the same keys.
var1 = [{'a':1,'b':2},{'c':2,'d':5,'h':4},{'c':2,'d':5,'e':4}]
var2 = [{'a':3,'b':2},{'c':1,'d':5,'h':4},{'c':5,'d':5,'e':4}]
res = []
for i in range(len(var1)):
dic = {}
dic1, dic2 = var1[i], var2[i]
for key, val in dic1.items(): // dic1.iteritems() in python 2.
dic[key] = dic1[key] + dic2[key]
res.append(dic)
>>>print(res)
[{'a': 4, 'b': 4}, {'c': 3, 'd': 10, 'h': 8}, {'c': 7, 'd': 10, 'e': 8}]
var1 = [{'a': 1, 'b': 2}, {'c': 2, 'd': 5, 'h': 4}, {'c': 2, 'd': 5, 'e': 4}]
var2 = [{'a': 3, 'b': 2}, {'c': 1, 'd': 5, 'h': 4}, {'c': 5, 'd': 5, 'e': 4}]
ret = []
for i, ele in enumerate(var1):
d = {}
for k, v in ele.items():
value = v
value += var2[i][k]
d[k] = value
ret.append(d)
print(ret)
For the sake of completeness, another zip-based one-liner that will work even if the dicts are uneven in the both lists:
result = [{k: d1.get(k, 0) + d2.get(k, 0) for k in set(d1) | set(d2)} for d1, d2 in zip(var1, var2)]
Would something like this help?
ar1 = [{'a':1,'b':2},{'c':2,'d':5,'h':4},{'c':2,'d':5,'e':4}]
var2 = [{'a':3,'b':2},{'c':1,'d':5,'h':4},{'c':5,'d':5,'e':4}]
combined_var = zip(var1, var2)
new_d = {}
list_new_ds = []
for i, j in combined_var:
new_d = {}
for key in i and j:
new_d[key] = i[key] + j[key]
list_new_ds.append(new_d)
list_new_ds = [{'a': 4, 'b': 4}, {'h': 8, 'c': 3, 'd': 10}, {'c': 7, 'e': 8, 'd': 10}]
To explain, the zip function merges the lists as a list of tuples. I then unpack the tuples and iterate through the keys in each dictionary and add the values for the same keys together using a new dictionary to store them. I then append the value to a list, and then re-initialise the temporary dictionary to empty before looking at the next tuple in the zipped list.
The order is different due to dictionary behaviour I believe.
I am a novice, so would appreciate any critiques of my answer!
I have a list of lists of data:
[[1422029700000, 230.84, 230.42, 230.31, 230.32, 378], [1422029800000, 231.84, 231.42, 231.31, 231.32, 379], ...]
and a list of keys:
['a', 'b', 'c', 'd', 'e']
I want to combine them to a dictionary of lists so it looks like:
['a': [1422029700000, 1422029800000], 'b': [230.84, 231.84], ...]
I can do this using loops but I am looking for a pythonic way.
It is quite simple:
In [1]: keys = ['a','b','c']
In [2]: values = [[1,2,3],[4,5,6],[7,8,9]]
In [7]: dict(zip(keys, zip(*values)))
Out[7]: {'a': (1, 4, 7), 'b': (2, 5, 8), 'c': (3, 6, 9)}
If you need lists as values:
In [8]: dict(zip(keys, [list(t) for t in zip(*values)]))
Out[8]: {'a': [1, 4, 7], 'b': [2, 5, 8], 'c': [3, 6, 9]}
or:
In [9]: dict(zip(keys, map(list, zip(*values))))
Out[9]: {'a': [1, 4, 7], 'b': [2, 5, 8], 'c': [3, 6, 9]}
Use:
{k: [d[i] for d in data] for i, k in enumerate(keys)}
Example:
>>> data=[[1422029700000, 230.84, 230.42, 230.31, 230.32, 378], [1422029800000, 231.84, 231.42, 231.31, 231.32, 379]]
>>> keys = ["a", "b", "c"]
>>> {k: [d[i] for d in data] for i, k in enumerate(keys)}
{'c': [230.42, 231.42], 'a': [1422029700000, 1422029800000], 'b': [230.84, 231.84]}
Your question has everything in a list so if you want a list of dicts:
l1= [[1422029700000, 230.84, 230.42, 230.31, 230.32, 378], [1422029800000, 231.84, 231.42, 231.31, 231.32, 379]]
l2 = ['a', 'b', 'c', 'd', 'e',"f"] # added f to match length of sublists
print([{a:list(b)} for a,b in zip(l2,zip(*l1))])
[{'a': [1422029700000, 1422029800000]}, {'b': [230.84, 231.84]}, {'c': [230.42, 231.42]}, {'d': [230.31, 231.31]}, {'e': [230.32, 231.32]}, {'f': [378, 379]}]
If you actually want a dict use a dict comprehension with zip:
print({a:list(b) for a,b in zip(l2,zip(*l1))})
{'f': [378, 379], 'e': [230.32, 231.32], 'a': [1422029700000, 1422029800000], 'b': [230.84, 231.84], 'c': [230.42, 231.42], 'd': [230.31, 231.31]}
You example also has a list of keys shorter than the length of your sublists so zipping will actually mean you lose values from your sublists so you may want to address that.
If you are using python2 you can use itertools.izip:
from itertools import izip
print({a:list(b) for a,b in izip(l2,zip(*l1))
I know that I can set a key-value pair by using
dict[key] = value
but I have a very long list of dicts of the type
dict = [{a:1, b:2, c:3, d:4},
{a:2, b:3, c:4, d:5},
{a:5, b:7, c:3, d:9}]
and I'd like to do something along the lines of
dict = map(lambda x: x['d'] <- x['d'] -1, dict)
how would I go about this? (This is a very simplified example so I'm not really trying to just subtract a number from all items by a particular key)
expected output would be in this case and not the general case I'm looking for
[{a:1, b:2, c:3, d:3},
{a:2, b:3, c:4, d:4},
{a:5, b:7, c:3, d:8}]
EDIT: 2
I believe the following does not work - so any similar solution would be helpful:
dict = map(lambda x: x.update(d, x[d] - 1), dict)
dicts = [{'a':1, 'b':2, 'c':3, 'd':4},
{'a':2, 'b':3, 'c':4, 'd':5},
{'a':5, 'b':7, 'c':3, 'd':9}]
for d in dicts:
d['d'] -= 1
Output:
In [94]: dicts
Out[94]:
[{'d': 3, 'b': 2, 'c': 3, 'a': 1},
{'d': 4, 'b': 3, 'c': 4, 'a': 2},
{'d': 8, 'b': 7, 'c': 3, 'a': 5}]
how about this: as exactly you said
>>> dicts = [{'a':1, 'b':2, 'c':3, 'd':4},
{'a':2, 'b':3, 'c':4, 'd':5},
{'a':5, 'b':7, 'c':3, 'd':9}]
>>> map(lambda x:x.update([('d',x['d']-1)]),dicts)
[None, None, None]
>>> dicts
[{'a': 1, 'c': 3, 'b': 2, 'd': 3}, {'a': 2, 'c': 4, 'b': 3, 'd': 4}, {'a': 5, 'c': 3, 'b': 7, 'd': 8}]
update will update the dictionary with (key,value) pair. Returns None
map is a way of transforming an iterable to a list by performing the same operation on every item from the iterable. I don't think that's what you want to do here, and it has confused you.
On the face of it (although you haven't mentioned what the real operation is that you want to perform) a simple for is all that is necessary:
dict_list = [
{'a': 1, 'b': 2, 'c': 3, 'd': 4},
{'a': 2, 'b': 3, 'c': 4, 'd': 5},
{'a': 5, 'b': 7, 'c': 3, 'd': 9},
]
for d in dict_list:
d['d'] -= 1
print(d)
output
{'a': 1, 'b': 2, 'c': 3, 'd': 3}
{'a': 2, 'b': 3, 'c': 4, 'd': 4}
{'a': 5, 'b': 7, 'c': 3, 'd': 8}
Using dict.__setitem__ and temporary list (or any other collection typer) trick:
>>> dicts = [{'a':1, 'b':2, 'c':3, 'd':4},
... {'a':2, 'b':3, 'c':4, 'd':5},
... {'a':5, 'b':7, 'c':3, 'd':9}]
>>> map(lambda d: [d.__setitem__('d', d['d'] - 1), d][1], dicts)
[{'a': 1, 'c': 3, 'b': 2, 'd': 3},
{'a': 2, 'c': 4, 'b': 3, 'd': 4},
{'a': 5, 'c': 3, 'b': 7, 'd': 8}]
Using simple for loop is moe recommended way. Especially there's a side effect in the function.
BTW, don't use dict as a variable name. It will shadows builtin function/type dict.
How about this:
my_dict = {k: f(v) for k, v in my_dict.iteritems()}
where f is whatever function you want.