I have a list of dictionary as follows.
mylist = [ {"0": ["code1", "code5"], "1" ["code8", "code7", "code2"]},
{"1": ["code2", "code3"], "2" ["code4", "code5", "code7"], "3": ["code1", "code10"]},
{"0": ["code8", "code5", "code1"], "2" ["code7", "code5", "code2"]} ]
Now, I want to calculate the codes count for each key in the dictionary. For example "0": ["code1", "code5"] and "0": ["code8", "code5"] should give: mydict_for_0 = {"code1": 1, "code5": 2, "code8": 1}
So, for the above mylist the output should be;
mydict_for_0 = {"code1": 2, "code5": 2, "code8": 1}
mydict_for_1 = {"code2": 2, "code3": 1, "code7": 1, "code8": 1}
mydict_for_2 = {"code4": 1, "code5": 2, "code7": 2, {"code2": 1}
mydict_for_3 = {"code1": 1, "code10": 1}
Please help me to do this using python!
Try with defaultdict, Counter from collections module, find all same key's value list, extend them into one list, save into a defaultdict(list):
from collections import defaultdict, Counter
new_dict = defaultdict(list)
for e in mylist:
for key,value in e.items():
new_dict[key].extend(value)
new_dict will be:
defaultdict(list,
{'0': ['code1', 'code5', 'code8', 'code5', 'code1'],
'1': ['code8', 'code7', 'code2', 'code2', 'code3'],
'2': ['code4', 'code5', 'code7', 'code7', 'code5', 'code2'],
'3': ['code1', 'code10']})
After that, loop all items to pass the values list into Counter, to count the occurrences of list:
result = {}
for key,value in new_dict.items():
result['mydict_for_'+key] = dict(Counter(value))
result will be:
{'mydict_for_0': {'code1': 2, 'code5': 2, 'code8': 1},
'mydict_for_1': {'code2': 2, 'code3': 1, 'code7': 1, 'code8': 1},
'mydict_for_2': {'code2': 1, 'code4': 1, 'code5': 2, 'code7': 2},
'mydict_for_3': {'code1': 1, 'code10': 1}}
This might be the solution
final_result = []
for i in mylist:
current_list = mylist[i]
d = {}
for key in current_list:
try:
d[m]+=1
except KeyError as e:
d.update({m: 1})
final_result.append(d)
for i in final_result:
print(i)
Related
I have a list:
List_ = ["Peter", "Peter", "Susan"]
I want to make a dictonary like this:
Dict_ = {"Name": "Peter", "Count": 2, "Name": "Susan", "Count": 1}
Dict_ = {}
Dict_new = {}
for text in List_:
if text not in Dict_:
Dict_[text] = 1
else:
Dict_[text] += 1
for key, values in Dict_.items():
Dict_new["Name"] = key
Dict_new["Count"] = values
print(Dict_new)
It is printing only last ones:
{"Name": "Susan", "Count": 1}
Here is the implementation that you can use according to what you would like :
from collections import Counter
# Your data
my_list = ["Peter", "Peter", "Susan"]
# Count the occurrences
counted = Counter(my_list)
# Your format
counted_list = []
for key, value in counted.items():
counted_list.append({"Name": key, "Count": value})
print(counted_list)
And output will be :
[{'Name': 'Peter', 'Count': 2}, {'Name': 'Susan', 'Count': 1}]
As noted in comments, a dictionary can only have each key once.
You may want a list of dictionaries, built with help from collections.Counter and a list comprehension.
>>> from collections import Counter
>>> List_ = ["Peter", "Peter", "Susan"]
>>> [{'name': k, 'count': v} for k, v in Counter(List_).items()]
[{'name': 'Peter', 'count': 2}, {'name': 'Susan', 'count': 1}]
In addition to using collections.Counter you could use a defaultdict.
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> for n in List_:
... d[n] += 1
...
>>> d
defaultdict(<class 'int'>, {'Peter': 2, 'Susan': 1})
>>> [{'name': k, 'count': v} for k, v in d.items()]
[{'name': 'Peter', 'count': 2}, {'name': 'Susan', 'count': 1}]
You can use the following code to achieve what you are trying to do.
List_ = ["Peter", "Peter", "Susan"]
dict_ = {}
for name in List_:
if name in dict_:
dict_[name] += 1
else:
dict_[name] = 1
print(dict_)
Generates the following output where key is the name and value is the count.
{'Peter': 2, 'Susan': 1}
I have this json with different levels:
[{'A': 1, 'B': 2, 'CA': {'CA1': '3', 'CA23': '4'}},
{'A': 1, 'B': {'CA1': '3'}, 'CA': {'CA1': '3', 'CA23': '4'}}]
And I want to get only the values for each row using list comprehension:
The expected result is:
[[1, 2, '3', '4'], [1, '3', '3', '4']]
Without using list comprehension this code work:
values = []
for row in json:
rows = []
for item in row.items():
if str(row[item[0]]).startswith("{"):
temp = row[item[0]].values()
else:
temp = [row[item[0]]]
rows.extend(temp)
values.append(rows)
Some ideas?
Here's a way to do it that cheats a little by using an auxiliary helper function to flatten the nested dictionary objects comprising each "row" of your data-structure.
import json # For pretty-printing data and results.
from collections.abc import MutableMapping
def flatten(nested):
''' Yield values from nested dictionary data structure. '''
for value in nested.values():
if isinstance(value, MutableMapping): # Nested?
yield from flatten(value)
else:
yield value
json_values = [{'A': 1, 'B': 2, 'CA': {'CA1': '3', 'CA23': '4'}},
{'A': 1, 'B': {'CA1': '3'}, 'CA': {'CA1': '3', 'CA23': '4'}}]
print('Before:')
print(json.dumps(json_values, indent=4))
# Here's the list comprehension.
result = [list(flatten(nested)) for nested in json_values]
print()
print('After:')
print(json.dumps(result, indent=4))
Output:
Before:
[
{
"A": 1,
"B": 2,
"CA": {
"CA1": "3",
"CA23": "4"
}
},
{
"A": 1,
"B": {
"CA1": "3"
},
"CA": {
"CA1": "3",
"CA23": "4"
}
}
]
After:
[
[
1,
2,
"3",
"4"
],
[
1,
"3",
"3",
"4"
]
]
Starting form a list:
user1 = ['alternative', 'rock', 'pop']
I can populate a dictionary with the number of appearences of each item.
u1={}
for tag in user1:
u1[tag]=1
print u1
and get: {'alternative': 1, 'pop': 1, 'rock': 1}
likewise, for:
user2 = ['indie', 'rock', 'chamber pop']
the same:
u2={}
for tag in user2:
u2[tag]=1
print u2
and get: {'indie': 1, 'chamber pop': 1, 'rock': 1}, and so on.
but lets say I want to populate this dict in the same fashion:
users = {
u1:{},
u2:{},
u3:{},
...
...
}
how can I do it?
Let's say you have users and lists already stored to a dictionary. Then you could iterate over all key value pairs within dictionary comprehension and use Counter to convert the list to dict with counts:
from collections import Counter
users = {
'u1': ['alternative', 'rock', 'pop'],
'u2': ['indie', 'rock', 'chamber pop'],
'u3': ['indie', 'rock', 'alternative', 'rock']
}
res = {k: Counter(v) for k, v in users.items()}
print(res)
Output:
{'u1': Counter({'alternative': 1, 'pop': 1, 'rock': 1}),
'u3': Counter({'rock': 2, 'indie': 1, 'alternative': 1}),
'u2': Counter({'indie': 1, 'chamber pop': 1, 'rock': 1})}
To break above a bit users.items() returns an iterable of (key, value) tuples:
>>> list(users.items())
[('u2', ['indie', 'rock', 'chamber pop']), ('u1', ['alternative', 'rock', 'pop']), ('u3', ['indie', 'rock', 'alternative', 'rock'])]
Then dict comprehension turns the list to dict containing the counts:
>>> Counter(['indie', 'rock', 'chamber pop'])
Counter({'rock': 1, 'indie': 1, 'chamber pop': 1})
Finally for each the user name and resulting Counter are added the to the result dict.
Counter is a good option. But according to this question we can use more simple option. Check this out.
users = {
'u1': ['alternative', 'rock', 'pop'],
'u2': ['indie', 'rock', 'chamber pop'],
}
res = {}
for user in users.items(): # return each key:value pair as tuple
res[user[0]] = {} # first element of tuple used as key in `res` for each list
for tag in user[1]: # return each element of list
res[user[0]][tag] = 1 # assign value as 1 of each element.
print res
Output:
{'u1': {'alternative': 1, 'pop': 1, 'rock': 1}, 'u2': {'indie': 1, 'chamber pop': 1, 'rock': 1}}
I have a nested dictionary {1: {2: {3: None}}} and a dictionary that maps keys of the nested dictionary to a set of values such as {1: x, 2: y, 3: z}. I want to transform the nested dictionary to this form {x: {y: {z: None}}}. I have tried a couple of recursive functions but I keep going in circles and confusing myself. What is the best way to achieve this?
The level of nesting is arbitrary. The above is a simple example.
You need to recurse through the dictionary while building a new one with new keys. Note that if you have a list or tuple in there somewhere that has other dictionaries in it, they won't be processed - you'd have to add some code to do that. You can actually do this without building a new dictionary, but I think this way is simpler.
od = { 1: { 2: { 3: None }}}
kd = { 1: 'x', 2: 'y', 3: 'z' }
def replace_keys(old_dict, key_dict):
new_dict = { }
for key in old_dict.keys():
new_key = key_dict.get(key, key)
if isinstance(old_dict[key], dict):
new_dict[new_key] = replace_keys(old_dict[key], key_dict)
else:
new_dict[new_key] = old_dict[key]
return new_dict
nd = replace_keys(od, kd)
print nd
outputs:
{'x': {'y': {'z': None}}}
The accepted answer will not support dict of list, adding the full feature
#bilentor,
od = {'name': 'John', '1': [{'name': 'innername'}]}
kd = { 'name': 'cname', '1': '2', 3: 'z' }
def replace_keys(data_dict, key_dict):
new_dict = { }
if isinstance(data_dict, list):
dict_value_list = list()
for inner_dict in data_dict:
dict_value_list.append(replace_keys(inner_dict, key_dict))
return dict_value_list
else:
for key in data_dict.keys():
value = data_dict[key]
new_key = key_dict.get(key, key)
if isinstance(value, dict) or isinstance(value, list):
new_dict[new_key] = replace_keys(value, key_dict)
else:
new_dict[new_key] = value
return new_dict
nd = replace_keys(od, kd)
print(nd)
You can use a NestedDict
from ndicts import NestedDict
d = {1: {2: {3: None}}}
replace = {1: 'x', 2: 'y', 3: 'z'}
def ndict_replace(ndict: dict, map: dict):
nd = NestedDict(nd)
new_nd = NestedDict()
for key, value in nd.items():
new_key = tuple(replace.get(k, k) for k in key)
new_nd[new_key] = value
return new_nd.to_dict()
>>> ndict_replace(d, replace)
{'x': {'y': {'z': None}}}
The solution is robust and works with any nested dictionary
>>> d = {
1: {2: {3: None}},
3: {4: None},
5: None
}
>>> ndict_replace(d, replace)
{'x': {'y': {'z': None}}, 'z': {4: None}, 4: None}}
To install ndicts pip install ndicts
I want to merge the contents of the following two dictionaries
>>> key_dict
{
'1': 'seq',
'0': 'seq',
'2': 'seq'
}
>>> value_dict
{
'tedious; repetitive and boring': 'text',
'worldly': 'text',
'ordinary': 'text'
}
Such that in the final list I have something like
>>>final_list
[
{
'seq': 0,
'text': 'worldly'
},
{
'seq': 1,
'text': 'tedious; repetitive and boring'
},
{
'seq': 2,
'text': 'ordinary'
}
]
EDIT:
Apologies, I tried this
>>> final_list = []
>>> temp_dict = {}
>>> for (key1, value1), (key2, value2) in zip(key_dict.items(), value_dict.items()):
... temp_dict[value1] = key1
... temp_dict[value2] = key2
... final_list.append[temp_dict]
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
TypeError: 'builtin_function_or_method' object is not subscriptable
>>>
Any help on where am I going wrong
Edit 2:
After correcting, final_list.append[temp_dict] to final_list.append(temp_dict)
I get this
>>> pprint(final_list)
[{'seq': '1', 'text': 'ordinary'},
{'seq': '1', 'text': 'ordinary'},
{'seq': '1', 'text': 'ordinary'}]
>>>
Can somebody explain why the values are getting repeated, I am not able to comprehend that.
You are actually on the right track. Values are repeating because you don't empty temp_dict at the end of each iteration. In fact, you don't even need temp_dict at all, just do:
>>> for (key1, value1), (key2, value2) in zip(key_dict.items(), value_dict.items()):
... final_list.append({value1: int(key1), value2: key2})
[{'seq': 1, 'text': 'ordinary'},
{'seq': 0, 'text': 'tedious; repetitive and boring'},
{'seq': 2, 'text': 'worldly'}]
If order matters, then you should use collections.OrderedDict instead of normal a dict.
With the order as specified in the question
from collections import OrderedDict
from pprint import pprint
key_dict = {
'1': 'seq',
'0': 'seq',
'2': 'seq'
}
value_dict = {
'tedious; repetitive and boring': 'text',
'worldly': 'text',
'ordinary': 'text'
}
kds = OrderedDict(sorted(kv for kv in key_dict.items()))
vds = OrderedDict(sorted((kv for kv in value_dict.items()), reverse=True))
d = [{v1: int(k1), v2: k2} for (k1, v1), (k2, v2) in zip(kds.items(), vds.items())]
pprint(d)
Output:
[{'seq': 0, 'text': 'worldly'},
{'seq': 1, 'text': 'tedious; repetitive and boring'},
{'seq': 2, 'text': 'ordinary'}]
The issue with your original code could have been resolved by moving temp_dict inside the loop.
e.g.
final_list = []
for (key1, value1), (key2, value2) in zip(key_dict.items(), value_dict.items()):
temp_dict = {}
temp_dict[value1] = key1
temp_dict[value2] = key2
final_list.append(temp_dict)