Get keys of dictionary based on rules - python

given a dictionary
dictionary = {'Animal 1': {'Dog': 'Yes', 'Cat': 'No', 'Color': 'Black'},
'Animal 2': {'Dog': 'Yes', 'Cat': 'No', 'Color': 'Brown'},
'Animal 3': {'Dog': 'No', 'Cat': 'Yes', 'Color': 'Grey'}}
How do I select the Animals that are dogs?
expected output ['Animal 1','Animal 2']
I could use:
pd.DataFrame.from_dict(dictionary).T.loc[pd.DataFrame.from_dict(dictionary).T["Dog"]=='Yes',:].index.to_list()
but it looks very ugly

You can use list comprehension:
dictionary = {
"Animal 1": {"Dog": "Yes", "Cat": "No", "Color": "Black"},
"Animal 2": {"Dog": "Yes", "Cat": "No", "Color": "Brown"},
"Animal 3": {"Dog": "No", "Cat": "Yes", "Color": "Grey"},
}
out = [k for k, d in dictionary.items() if d.get("Dog") == "Yes"]
print(out)
Prints:
['Animal 1', 'Animal 2']

The pandas version could be trimmed by using an intermediate variable so that you don't double calculate the mask. And you don't need .loc for this filter.
df = pd.DataFrame.from_dict(dictionary).T
dogs = df[df["Dog"] == "Yes"].index.to_list()
But this is still complex compared to running through the dict items in another answer to this question. It would only be interesting if there was some future need of the dataframe.

Related

How can I collect key-value pairs of dictionaries into one large dictionary in Python?

I have a dictionary in the following format:
data = {
'Bob': {
'age': 12,
'weight': 150,
'eye_color': 'blue'
},
'Jim': {
'favorite_food': 'cherries',
'sport': 'baseball',
'hobby': 'running'
},
'Tom': {
'strength': 'average',
'endurance': 'high',
'heart_rate': 'low'
}
}
What is the most Pythonic way to concatenate all of the dictionaries within dict into a new dictionary so that I would end up with something like the following:
new_dict = {
'age': 12,
'weight': 150,
'eye_color': 'blue',
'favorite_food': 'cherries',
'sport': 'baseball',
'hobby': 'running',
'strength': 'average',
'endurance': 'high',
'heart_rate': 'low'
}
You can use functools.reduce() to build up the result, unioning one dictionary at a time:
from functools import reduce
data = {
'Bob' : { 'age': 12, 'weight': 150, 'eye_color': 'blue' },
'Jim' : { 'favorite_food': 'cherries', 'sport': 'baseball', 'hobby': 'running' },
'Tom' : { 'strength': 'average', 'endurance': 'high', 'hear_rate': 'low' }
}
result = reduce(lambda x, y: dict(**x, **y), data.values(), {})
print(result)
This outputs:
{'age': 12, 'weight': 150, 'eye_color': 'blue', 'favorite_food': 'cherries',
'sport': 'baseball', 'hobby': 'running', 'strength': 'average',
'endurance': 'high', 'hear_rate': 'low'}
On Python 3.9 or higher, you can use lambda x: x | y, operator.or_, or dict.__or__ instead of lambda x: dict(**x, **y) if you're on Python 3.9 or higher. The latter two are from a suggestion by Mad Physicist.
One option is to use a dictionary comprehension with a nested generator expression:
new_dict = {k: v for d in data.values() for k, v in d.items()}
Another way that's subtly different to to use collections.ChainMap:
new_dict = collections. ChainMap(*data.values())
In this case, new_dict will not be a dict, but will quack like one just fine. Lookup will be a bit slower, but construction will be faster.

add value of nested dictionary if key exists

I am having a code. I took it from stack overflow only
below is the code
def does_nested_key_exists(dictionary, nested_key, keys=None):
if keys is None:
keys = []
for key, value in dictionary.items():
if key == nested_key:
return True, '.'.join(keys)
if isinstance(value, dict):
keys.append(key)
return does_nested_key_exists(value, nested_key, keys)
return False, ""
menu = {'dinner':
{'chicken':'good',
'beef':'average',
'vegetarian':{
'tofu':'good',
'salad':{
'caeser':'bad',
'italian':'average'}
},
'pork':'bad'}
}
What I need is if suppose a new key suppose green_veg having parent as vegetarian exists (as it is), I need to add the green_veg key under same parent key vegetarian. Suppose if parent key does not exist, i want to add to main dict like direct key for dict menu
How can i achieve this
Look at the two examples:
{"green_veg": "bad"} with parent vegetarian, where the parent is present in the dictionary named menu.
{"green_veg": "bad"} with parent greens, where the parent is not present in the dictionary named menu.
Process examples are also given.
Here is the code:
class Solution:
def __init__(self) -> None:
self.parents = []
def fun(self, dikt: dict, find_key, new_key):
if find_key in dikt:
dikt[find_key][new_key] = {}
return True
f = False
for key, value in dikt.items():
if isinstance(value, dict):
f = f or self.fun(value, find_key, new_key)
return f
def call(self, dikt: dict, find_key, new_key):
p = self.fun(dikt, find_key, new_key)
if not p:
dikt[new_key] = {}
Example 1 (from question)
menu = {
"dinner": {
"chicken": "good",
"beef": "average",
"vegetarian": {
"tofu": "good",
"salad": {"caeser": "bad", "italian": "average"},
},
"pork": "bad",
}
}
print(menu)
Solution().call(menu, "vegetarian", "green_veg")
print(menu)
Solution().call(menu, "greens", "green_veg")
print(menu)
Here is the output:
{'dinner': {'chicken': 'good', 'beef': 'average', 'vegetarian': {'tofu': 'good', 'salad': {'caeser': 'bad', 'italian': 'average'}}, 'pork': 'bad'}}
{'dinner': {'chicken': 'good', 'beef': 'average', 'vegetarian': {'tofu': 'good', 'salad': {'caeser': 'bad', 'italian': 'average'}, 'green_veg': {}}, 'pork': 'bad'}}
{'dinner': {'chicken': 'good', 'beef': 'average', 'vegetarian': {'tofu': 'good', 'salad': {'caeser': 'bad', 'italian': 'average'}, 'green_veg': {}}, 'pork': 'bad'}, 'green_veg': {}}
Example 2 (from comments)
menu = {}
print(menu)
Solution().call(menu, "None", "p1")
Solution().call(menu, "p1", "p2")
Solution().call(menu, "p2", "p3")
print(menu)
Here is the output:
{}
{'p1': {'p2': {'p3': {}}}}
menu = {
"dinner": {
"chicken": "good",
"beef": "average",
"vegetarian": {
"tofu": "good",
"salad": {"caeser": "bad", "italian": "average"},
},
"pork": "bad",
}
}
def menuItems(dict,type,target,keys):
if(target in dict[type].keys()):
dict[type][target][keys[0]]=keys[1]
else:
dict[type][keys[0]]=keys[1]
menuItems(menu,'dinner','vegitarian',['green_veg','bad'])
print(menu)
output:
{'dinner': {'chicken': 'good', 'beef': 'average', 'vegetarian': {'tofu': 'good', 'salad': {'caeser': 'bad', 'italian': 'average'}}, 'pork': 'bad', 'green_veg': 'bad'}}
theory:
->check weather the key exist or not in parent
->if exist create a new key with value in that key
->else create a key in parent which is type in above code
I think it may help you to understand the basic concept of dictionaries in python.

Join dictionaries so that previous dictionary names are now 2nd layer keys?

I am attempting to organize new dictionaries based on the results of a df.groupby('fruits'). I now have dictionaries setup like the following,
print(type(flavors))
<class 'dict'>
print(flavors)
{'apples':['crisp', 'tart'],
'oranges':['citrusy','juicy', 'sour'],
'bananas':['sweet']}
print(colors)
{'apples':['red', 'green'],
'oranges':['orange','orange', 'rotten'],
'bananas':['yellow']}
print(farms)
{'apples':['upstate orchard', 'dreamy estates'],
'oranges':['crop culture','sandy bay', 'heartland'],
'bananas':['horticulture heros']}
How could I join them in a new dictionary like the following?
print(fruits_dict)
{'apples': {'flavors': ['crisp', 'tart'],
'colors': ['red', 'green'],
'farms': ['upstate orchard', 'dreamy estates'] },
'oranges': {'flavors': ['citrusy','juicy', 'sour'],
'colors': ['orange','orange', 'rotten'],
'farms': ['crop culture','sandy bay', 'heartland'] },
'bananas': {'flavors': ['sweet'],
'colors': ['yellow'],
'farms': ['horticulture heros'] } }
dicts = {'flavors' : flavors, 'colors': colors, 'farms' : farms}
result = {key: { k : dicts[k][key] for k in dicts} for key in flavors}
You can use this example with dict comprehension how to get your output:
flavors = {
"apples": ["crisp", "tart"],
"oranges": ["citrusy", "juicy", "sour"],
"bananas": ["sweet"],
}
colors = {
"apples": ["red", "green"],
"oranges": ["orange", "orange", "rotten"],
"bananas": ["yellow"],
}
farms = {
"apples": ["upstate orchard", "dreamy estates"],
"oranges": ["crop culture", "sandy bay", "heartland"],
"bananas": ["horticulture heros"],
}
out = {
k: {
"flavors": flavors.get(k, []),
"colors": colors.get(k, []),
"farms": farms.get(k, []),
}
for k in (flavors.keys() & colors.keys() & farms.keys())
}
from pprint import pprint
pprint(out)
Prints:
{'apples': {'colors': ['red', 'green'],
'farms': ['upstate orchard', 'dreamy estates'],
'flavors': ['crisp', 'tart']},
'bananas': {'colors': ['yellow'],
'farms': ['horticulture heros'],
'flavors': ['sweet']},
'oranges': {'colors': ['orange', 'orange', 'rotten'],
'farms': ['crop culture', 'sandy bay', 'heartland'],
'flavors': ['citrusy', 'juicy', 'sour']}}

Creating a dictionary from two lists in python

I have a JSON data as below.
input_list = [["Richard",[],{"children":"yes","divorced":"no","occupation":"analyst"}],
["Mary",["testing"],{"children":"no","divorced":"yes","occupation":"QA analyst","location":"Seattle"}]]
I have another list where I have the prospective keys present
list_keys = ['name', 'current_project', 'details']
I am trying to create a dic using both to make the data usable for metrics
I have summarized the both the list for the question but it goes on forever, there are multiple elements in the list. input_list is a nested list which has 500k+ elements and each list element have 70+ elements of their own (expect the details one)
list_keys also have 70+ elements in it.
I was trying to create a dict using zip but that its not helping given the size of data, also with zip I am not able to exclude the "details" element from
I am expecting output something like this.
[
{
"name": "Richard",
"current_project": "",
"children": "yes",
"divorced": "no",
"occupation": "analyst"
},
{
"name": "Mary",
"current_project" :"testing",
"children": "no",
"divorced": "yes",
"occupation": "QA analyst",
"location": "Seattle"
}
]
I have tried this so far
>>> for line in input_list:
... zipbObj = zip(list_keys, line)
... dictOfWords = dict(zipbObj)
...
>>> print dictOfWords
{'current_project': ['testing'], 'name': 'Mary', 'details': {'location': 'Seattle', 'children': 'no', 'divorced': 'yes', 'occupation': 'QA analyst'}}
but with this I am unable to to get rid of nested dict key "details". so looking for help with that
Seems like what you wanted was a list of dictionaries, here is something i coded up in the terminal and copied in here. Hope it helps.
>>> list_of_dicts = []
>>> for item in input_list:
... dict = {}
... for i in range(0, len(item)-2, 3):
... dict[list_keys[0]] = item[i]
... dict[list_keys[1]] = item[i+1]
... dict.update(item[i+2])
... list_of_dicts.append(dict)
...
>>> list_of_dicts
[{'name': 'Richard', 'current_project': [], 'children': 'yes', 'divorced': 'no', 'occupation': 'analyst'
}, {'name': 'Mary', 'current_project': ['testing'], 'children': 'no', 'divorced': 'yes', 'occupation': '
QA analyst', 'location': 'Seattle'}]
I will mention it is not the ideal method of doing this since it relies on perfectly ordered items in the input_list.
people = input_list = [["Richard",[],{"children":"yes","divorced":"no","occupation":"analyst"}],
["Mary",["testing"],{"children":"no","divorced":"yes","occupation":"QA analyst","location":"Seattle"}]]
list_keys = ['name', 'current_project', 'details']
listout = []
for person in people:
dict_p = {}
for key in list_keys:
if not key == 'details':
dict_p[key] = person[list_keys.index(key)]
else:
subdict = person[list_keys.index(key)]
for subkey in subdict.keys():
dict_p[subkey] = subdict[subkey]
listout.append(dict_p)
listout
The issue with using zip is that you have that additional dictionary in the people list. This will get the following output, and should work through a larger list of individuals:
[{'name': 'Richard',
'current_project': [],
'children': 'yes',
'divorced': 'no',
'occupation': 'analyst'},
{'name': 'Mary',
'current_project': ['testing'],
'children': 'no',
'divorced': 'yes',
'occupation': 'QA analyst',
'location': 'Seattle'}]
This script will go through every item of input_list and creates new list where there aren't any list or dictionaries:
input_list = [
["Richard",[],{"children":"yes","divorced":"no","occupation":"analyst"}],
["Mary",["testing"],{"children":"no","divorced":"yes","occupation":"QA analyst","location":"Seattle"}]
]
list_keys = ['name', 'current_project', 'details']
out = []
for item in input_list:
d = {}
out.append(d)
for value, keyname in zip(item, list_keys):
if isinstance(value, dict):
d.update(**value)
elif isinstance(value, list):
if value:
d[keyname] = value[0]
else:
d[keyname] = ''
else:
d[keyname] = value
from pprint import pprint
pprint(out)
Prints:
[{'children': 'yes',
'current_project': '',
'divorced': 'no',
'name': 'Richard',
'occupation': 'analyst'},
{'children': 'no',
'current_project': 'testing',
'divorced': 'yes',
'location': 'Seattle',
'name': 'Mary',
'occupation': 'QA analyst'}]

Update values from a "default dictionary" without removing its keys [duplicate]

This question already has answers here:
Update value of a nested dictionary of varying depth
(28 answers)
Closed 4 years ago.
I have two dictionaries, the first is what the default values of the second one should fall back to if they are not present or not defined, and it is somewhat like this:
default_dict = {
'lorem': {
'foo': 'white',
'bar': 'black',
},
'ipsum': {
'xyz': '',
'abc': {},
'qwe': {}
}
}
And the second looks like this:
custom_dict = {
'lorem': {
'bar': 'blue',
},
'ipsum': {
'xyz': 'apple',
'qwe': { 'one': 'strawberry' }
}
}
Is there any way I can "update" from the default_dict with the values from the custom_dict?
The desired result would look something like this:
custom_dict = {
'lorem': {
'foo': 'white',
'bar': 'blue',
},
'ipsum': {
'xyz': 'apple',
'abc': {},
'qwe': { 'one': 'strawberry' }
}
}
I've tried doing default_dict.update(custom_dict) and then custom_dict = default_dict, but as you can imagine I'm just getting custom_dict back untouched... So the keys of default_dict are getting removed when it is updated.
Use:
d={a:b for k,v in custom_dict.items() for a,b in v.items()}
print({k:{a:d.get(a,b) for a,b in v.items()} for k,v in default_dict.items()})
A dictionary comprehension + a nested dictionary comprehension would work.
Output:
{'lorem': {'foo': 'white', 'bar': 'blue'}, 'ipsum': {'xyz': 'apple', 'abc': {}, 'qwe': {'one': 'strawberry'}}}
if the structure of your dictionaries are always like above so the following code works fine:
for item in default_dict:
for value in default_dict[item].keys():
if value not in custom_dict[item].keys():
custom_dict[item].update({value: default_dict[item][value]})
good luck

Categories