Need Help in Python Dictionary Related Task - python

Consider a dictionary,
dictionary = {
'AE':{'Applied':4, 'Programming':3 },
'BE':{'Applied':4, 'Programming':2 },
'CE':{'Applied':4, 'Programming':5 },
}
With comprehension in definition, yield the output as,
output = [['AE':'BE':'CE'],
['Applied', 2,4,5],
['Programming', 5,3,2]]

You can use this code:
dictionary = {
'AE':{'Applied':4, 'Programming':3 },
'BE':{'Applied':4, 'Programming':2 },
'CE':{'Applied':4, 'Programming':5 },
}
output = []
dict_keys = list(dictionary.keys())
output.append(dict_keys)
for key in dictionary[dict_keys[0]]:
value = [dictionary[k][key] for k in dict_keys]
value.insert(0, key)
output.append(value)
Output:
output = [['AE', 'BE', 'CE'], ['Applied', 4, 4, 4], ['Programming', 3, 2, 5]]

Related

Count number of objects in list of dictionary where a key's value is more than 1

Given a list of dictionaries:
data = {
"data": [
{
"categoryOptionCombo": {
"id": "A"
},
"dataElement": {
"id": "123"
}
},
{
"categoryOptionCombo": {
"id": "B"
},
"dataElement": {
"id": "123"
}
},
{
"categoryOptionCombo": {
"id": "C"
},
"dataElement": {
"id": "456"
}
}
]
}
I would like to display the dataElement where the count of distinct categoryOptionCombo is larger than 1.
e.g. the result of the function would be an iterable of IDs:
[123]
because the dataElement with id 123 has two different categoryOptionCombos.
tracker = {}
for d in data['data']:
data_element = d['dataElement']['id']
coc = d['categoryOptionCombo']['id']
if data_element not in tracker:
tracker[data_element] = set()
tracker[data_element].add(coc)
too_many = [key for key,value in tracker.items() if len(value) > 1]
How can I iterate the list of dictionaries preferably with a comprehension? This solution above is not pythonic.
One approach:
import collections
counts = collections.defaultdict(set)
for d in data["data"]:
counts[d["dataElement"]["id"]].add(d["categoryOptionCombo"]["id"])
res = [k for k, v in counts.items() if len(v) > 1]
print(res)
Output
['123']
This approach creates a dictionary mapping dataElements to the different types of categoryOptionCombo:
defaultdict(<class 'set'>, {'123': {'B', 'A'}, '456': {'C'}})
Almost a one-liner:
counts = collections.Counter( d['dataElement']['id'] for d in data['data'] )
print( counts )
Output:
Counter({'123': 2, '456': 1})
No need for sets, you can just remember each data element's first coc or mark it as having 'multiple'.
tracker = {}
for d in data['data']:
data_element = d['dataElement']['id']
coc = d['categoryOptionCombo']['id']
if tracker.setdefault(data_element, coc) != coc:
tracker[data_element] = 'multiple'
too_many = [key for key,value in tracker.items() if value == 'multiple']
(If the string 'multiple' can be a coc id, then use multiple = object() and compare with is).

Extract dictionary data which match with other dictionary

I've two dictionaries one original & the other reference. And I want to match reference dict keys with original dict keys and extract all those keys, values from original which are present in reference.
For example
original_dict = {
'a': {
'1': [1, 2, 3, 4, 5]
},
'b': {
'1': {
'A': [1, 2, 3, 4]
}
},
'c': {
'3': [1]
}
}
And a reference dictionary
reference_dict = {
'a': {
'2': [1, 2, 3]
},
'b': {
'1': {
'A': []
}
},
'c': {
'3': []
}
}
And this is the extracted dictionary.
extracted_dict = {
'b': {
'1': {
'A': [1, 2, 3, 4]
}
},
'c': {
'3': [1]
}
}
Here you might have noticed that I don't care about values of reference dict. All I want is the values of original dict.
You can use recursion to accomplish this:
def merge(value_dict, key_dict):
ret = {}
for key, subdict in key_dict.items():
if key in value_dict:
if not isinstance(value_dict[key], dict):
# we found a value so don't keep recursing
ret[key] = value_dict[key]
else:
# found another dict so merge subdicts
merged = merge(value_dict[key], subdict)
if len(merged) > 0:
ret[key] = merged
return ret
merge(original_dict, reference_dict)
I´m not sure if I understand your question 100% but this might be a solution.
we use relevant keys and put them in a list to use them on a .update() dict
new_lst = []
for i in original_dict.keys():
new_lst.append(original_dict[i])
reference_dict.clear()
for i in new_lst:
reference_dict.update(i)
print(reference_dict)

Unpack nodes of a dict for each slash in the key

I have a dict:
a = {
"group_a/category_a/metric_a": 5,
"group_a/category_a/metric_b": 4,
"group_a/category_b/metric_a": 3,
"group_a/category_b/metric_b": 2,
"group_b/category_a/metric_d": 1
}
I would like to unpack the nodes by creating a nested view, seperated by each slash, where the outcome looks as follows:
b = {
"group_a": {
"category_a": {
"metric_a": 5,
"metric_b": 4
},
"category_b": {
"metric_a": 3,
"metric_b": 2
},
"group_b": {
"category_a": {
"metric_d": 1
}
}
}
How can we go from a to b? I encountered this problem when trying to publish the dict above to Firebase as the nodes group_a/category_a/metric_a is not accepted, whereas a dict that is nested is allowed.
Loop through, split each key into a list of keys, create sub-dictionaries as required...
from pprint import pprint
a = {
"group_a/category_a/metric_a": 5,
"group_a/category_a/metric_b": 4,
"group_a/category_b/metric_a": 3,
"group_a/category_b/metric_b": 2,
"group_b/category_a/metric_d": 1
}
b = {}
for k, v in a.items():
dct = b
keys = k.split("/")
for key in keys[:-1]:
if key not in dct:
dct[key] = {}
dct = dct[key]
dct[keys[-1]] = v
pprint(b)
Gives:
{'group_a': {'category_a': {'metric_a': 5, 'metric_b': 4},
'category_b': {'metric_a': 3, 'metric_b': 2}},
'group_b': {'category_a': {'metric_d': 1}}}

Get unique dictionary but concatenate value of specific key

I am trying to devise a logic in python for the given scenario -
I have a list of multiple dictionaries, my main goal is to get the unique list of dictionary based on the id key.
non_unique = [
{"id": 1, "name": "A", "items": ["blah1"]},
{"id": 1, "name": "A", "items": ["blah2"]}
]
I can get the unique list of dictionaries by this dictionary comprehension:
list({v["id"]: v for v in non_unique}.values())
But I am unable to fit a logic in the dictionary comprehension to concatenate the value of items key. My expected output is:
[{"id": 1, "name": "A", "items": ["blah1", "blah2"]}]
Sometimes a simple for loop is much more clear than dict or list comprehension....in your case i would simple use :
from operator import itemgetter
non_unique = [{'id': 1, "name": "A", "items": ["blah1"]},
{'id': 1, "name": "A", "items": ["blah2"]},
{'id': 2, "name": "A", "items": ["blah2"]},
{'id': 2, "name": "B", "items": ["blah1"]},
]
result = {}
for uniq in non_unique:
id, items, name = itemgetter('id', 'items', 'name')(uniq)
if id in result:
result[id]["items"] += items
if name not in result[id]["name"].split():
result[id]["name"] += ",{}".format(name)
else:
result[id] = uniq
unique_list = [val for item, val in result.items()]
print(unique_list)
Output :
[{'id': 1, 'name': 'A', 'items': ['blah1', 'blah2']}, {'id': 2, 'name': 'A,B', 'items': ['blah2', 'blah1']}]
EDIT
As suggested in comments : i add a simple check for the name and add it to names if it does not exists....
I also add the itemgetter for getting a more "clear" code.
You can use this method.
non_unique = [
{'id': 1, 'name': "A", 'items': ["blah1"]},
{'id': 1, 'name': "A", 'items': ["blah2"]}
]
dic = []
for v in non_unique:
for x in dic:
if x['id'] == v['id']:
if v['name']not in x['name']:
x['name'] += v['name']
if v['items'] not in x['items']:
x['items'] += v['items']
break
else:
dic.append(v)
print(dic)
Output - [{'id': 1, 'name': 'A', 'items': ['blah1', 'blah2']}]

Need to create a layered dict from a flat one

I have a dict, that looks like this:
{
'foo': {
'opt1': 1,
'opt2': 2,
},
'foo/bar': {
'opt3': 3,
'opt4': 4,
},
'foo/bar/baz': {
'opt5': 5,
'opt6': 6,
}
}
And I need to get it to look like:
{
'foo': {
'opt1': 1,
'opt2': 2,
'bar': {
'opt3': 3,
'opt4': 4,
'baz': {
'opt5': 5,
'opt6': 6,
}
}
}
}
I should point out that there can and will be multiple top-level keys ('foo' in this case). I could probably throw something together to get what i need, but I was hoping that there is a solution that's more efficient.
Like this:
def nest(d):
rv = {}
for key, value in d.iteritems():
node = rv
for part in key.split('/'):
node = node.setdefault(part, {})
node.update(value)
return rv
def layer(dict):
for k,v in dict:
if '/' in k:
del dict[k]
subdict = dict.get(k[:k.find('/')],{})
subdict[k[k.find('/')+1:]] = v
layer(subdict)
Got this lib to print your dict in a better way. pprint.
https://docs.python.org/3.2/library/pprint.html

Categories

Resources