How to make all keys except first key lowercase in dictionary - python

Here is a dictionary
dict1 = {'math': {'JOHN': 7,
'LISA': 4,
'KARYN': 3},
'eng': {'LISA': 5,
'TOBY':4,
'KARYN':11,
'RYAN':3},
'phy': {'KARYN': 7,
'JOHN': 7,
'STEVE':9,
'JOE':9}}
I would like to make the all letters in the keys except the 1st lower case.
This is what i've attempted
for i in dict1:
dict1 = dict(k.lower(), v) for k =! k[0], v in dict1[i].items())
dict1
It's failing because i'm not exactly sure how to apply the condition so that only the 1st letter remains capital.

If I understand correctly:
>>> {k: {kk.capitalize(): vv for kk, vv in v.items()} for k, v in dict1.items()}
{'math': {'John': 7, 'Lisa': 4, 'Karyn': 3},
'eng': {'Lisa': 5, 'Toby': 4, 'Karyn': 11, 'Ryan': 3},
'phy': {'Karyn': 7, 'John': 7, 'Steve': 9, 'Joe': 9}}

You can just create a new dictionary using the new keys and delete the old one.
from collections import defaultdict
# this creates a dictionary of dictionaries
dict2 = defaultdict(dict)
for key in dict1.keys():
for name in dict1[key]:
# get only the first letter in caps and the rest in lower
newname = name[0] + name.lower()[1:]
# create a new entry in the new dictionray using the old one
dict2[key][newname] = dict1[key][name]
The output is:
defaultdict(dict,
{'eng': {'Karyn': 11, 'Lisa': 5, 'Ryan': 3, 'Toby': 4},
'math': {'John': 7, 'Karyn': 3, 'Lisa': 4},
'phy': {'Joe': 9, 'John': 7, 'Karyn': 7, 'Steve': 9}})
which can be assessed just like a regular dictionary.

In python there is a function called capitalize(). Maybe it could help?
your_string = "ABRAKADABRA!"
print(your_string.capitalize())
returns
Abrakadabra!
https://www.geeksforgeeks.org/string-capitalize-python/

Related

Given key value pairs, sort output alphabetically and increment values

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}

How to convert list of dictionaries to dictionaries

mylist = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
i want it as
myDict ={'a': 1, 'b': 2,'c': 3, 'd': 4,'e': 5, 'f': 6}
You can make use of ChainMap.
from collections import ChainMap
myDict = dict(ChainMap(*mylist ))
This will take each dictionary and iterate through its key value pairs in for (k,v) in elem.items() part and assign them to a new dictionary.
mylist = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
new_dict = {k:v for elem in mylist for (k,v) in elem.items()}
print new_dict
This will replace the duplicated keys.
I would create a new dictionary, iterate over the dictionaries in mylist, then iterate over the key/value pairs in that dictionary. From there, you can add each key/value pair to myDict.
mylist = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
myDict = {}
for Dict in mylist:
for key in Dict:
myDict[key] = Dict[key]
print(myDict)

Using reduce on a list of dictionaries of dictionaries

Here is the given list.
Pets = [{'f1': {'dogs': 2, 'cats': 3, 'fish': 1},
'f2': {'dogs': 3, 'cats': 2}},
{'f1': {'dogs': 5, 'cats': 2, 'fish': 3}}]
I need to use the map and reduce function so that I can have a final result of
{'dogs': 10, 'cats': 7, 'fish': 4}
I have written a function using map
def addDict(d):
d2 = {}
for outKey, inKey in d.items():
for inVal in inKey:
if inVal in d2:
d2[inVal] += inKey[inVal]
else:
d2[inVal] = inKey[inVal]
return d2
def addDictN(L):
d2 = list(map(addDict, L))
print(d2)
That returns
[{'dogs': 5, 'cats': 5, 'fish': 1}, {'dogs': 5, 'cats': 2, 'fish': 3}]
It combines the f1 and f2 of the first and second dictionaries, but I am unsure of how to use reduce on the dictionaries to get the final result.
You can use collections.Counter to sum your list of counter dictionaries.
Moreover, your dictionary flattening logic can be optimised via itertools.chain.
from itertools import chain
from collections import Counter
Pets = [{'f1': {'dogs': 2, 'cats': 3, 'fish': 1},
'f2': {'dogs': 3, 'cats': 2}},
{'f1': {'dogs': 5, 'cats': 2, 'fish': 3}}]
lst = list(chain.from_iterable([i.values() for i in Pets]))
lst_sum = sum(map(Counter, lst), Counter())
# Counter({'cats': 7, 'dogs': 10, 'fish': 4})
This works for an arbitrary length list of dictionaries, with no key matching requirements across dictionaries.
The second parameter of sum is a start value. It is set to an empty Counter object to avoid TypeError.
Without using map and reduce, I would be inclined to do something like this:
from collections import defaultdict
result = defaultdict()
for fdict in pets:
for f in fdict.keys():
for pet, count in fdict[f].items():
result[pet] += count
Using reduce (which really is not the right function for the job, and is not in Python 3) on your current progress would be something like this:
from collections import Counter
pets = [{'dogs': 5, 'cats': 5, 'fish': 1}, {'dogs': 5, 'cats': 2, 'fish': 3}]
result = reduce(lambda x, y: x + Counter(y), pets, Counter())
You can use purely map and reduce like so:
Pets = [{'f1': {'dogs': 2, 'cats': 3, 'fish': 1},
'f2': {'dogs': 3, 'cats': 2}},
{'f1': {'dogs': 5, 'cats': 2, 'fish': 3}}]
new_pets = reduce(lambda x, y:[b.items() for _, b in x.items()]+[b.items() for _, b in y.items()], Pets)
final_pets = dict(reduce(lambda x, y:map(lambda c:(c, dict(x).get(c, 0)+dict(y).get(c, 0)), ['dogs', 'cats', 'fish']), new_pets))
Output:
{'fish': 4, 'cats': 7, 'dogs': 10}

How to combine two list containing dictionary with similar keys?

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!

python sorting dictionary by length of values

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': []}]

Categories