Creating 2D dictionary in Python - python

I have a list of details from an output for "set1" which are like "name", "place", "animal", "thing"
and a "set2" with the same details.
I want to create a dictionary with dict_names[setx]['name']... etc On these lines.
Is that the best way to do it? If not how do I do it?
I am not sure how 2D works in dictionary.. Any pointers?

It would have the following syntax
dict_names = {
'd1': {
'name': 'bob',
'place': 'lawn',
'animal': 'man'
},
'd2': {
'name': 'spot',
'place': 'bed',
'animal': 'dog'
}
}
You can then look things up like
>>> dict_names['d1']['name']
'bob'
To assign a new inner dict
dict_names['d1'] = {'name': 'bob', 'place': 'lawn', 'animal': 'man'}
To assign a specific value to an inner dict
dict_names['d1']['name'] = 'fred'

Something like this would work:
set1 = {
'name': 'Michael',
'place': 'London',
...
}
# same for set2
d = dict()
d['set1'] = set1
d['set2'] = set2
Then you can do:
d['set1']['name']
etc. It is better to think about it as a nested structure (instead of a 2D matrix):
{
'set1': {
'name': 'Michael',
'place': 'London',
...
}
'set2': {
'name': 'Michael',
'place': 'London',
...
}
}
Take a look here for an easy way to visualize nested dictionaries.

Something like this should work.
dictionary = dict()
dictionary[1] = dict()
dictionary[1][1] = 3
print(dictionary[1][1])
You can extend it to higher dimensions as well.

If I understand your question properly, what you need here is a nested dictionary.You can use the addict module to create nested dictionaries quite easily.
https://github.com/mewwts/addict
if the items in each set is ordered, you could use the below approach
body = Dict()
setx = ['person1','berlin','cat']
sety = ['person2','jena','dog']
setz = ['person3','leipzig','tiger']
for set_,s in zip([setx,sety,setz],['x','y','z']):
for item,item_identifier in zip(set_,['name','city','animmal']):
body[f'set{s}'][f'{item_identifier}'] = item
now you can easily access the items as follows.
print(body['setx']['name'])

Simple one-liner for a nested 2D dictionary ( dict_names = {} ) :
dict_names.setdefault('KeyX',{})['KeyY']='Value'

Related

Extract part of a dictionary within a list by string condition in python

I have a list with dictionary contained within it in the format:
mydataset =
[{'thing1': 'pink',
'thing2': 'apple',
'thing3': 'car',
'data': [{'firstname': 'jenny',
'lastname': 'jones',
}]},
{'thing1': 'blue',
'thing2': 'banana',
'thing3': 'bicycle',
'data': [{'firstname': 'david',
'lastname': 'walls',
}]}]
I want to be able to extract all the items called firstname within 'data', i.e. 'jenny' and 'david'.
I've tried an approach of myextract = [x in x if mydataset['data']], but of course it fails because I think I'm looking for a value with that. My mental model of the data structure isn't right at the moment.
Try the following:
res = [i['data'][0]['firstname'] for i in mydataset]
output:
['jenny', 'david']
side note: please put banana and apple inside single quotes.
Use the following list comprehension:
res = [di["firstname"]for d in mydataset for di in d["data"] if "firstname" in di]
print(res)
Output
['jenny', 'david']
The above list comprehension is equivalent to the following for-loop:
res = []
for d in mydataset:
for di in d["data"]:
if "firstname" in di:
res.append(di["firstname"])
print(res)
Note that both solutions above will work for more than one element in the sub-dictionary d["data"] and even if the "firstname" key is not present.
For the sake of reusability you could also define a function that will let you access individual values in the dataset and use it for this particular example:
def nested_getitem(path, dic):
from operator import getitem
from functools import reduce
return reduce(getitem, path, dic)
res = [nested_getitem(["data", 0, "firstname"], d) for d in mydataset]
print(res)
Output
['jenny', 'david']

Nested dictionary comprehension (2 level)

I have a list of dictionary objects
data = [
{
'id': 1,
'parent_id': 101 ,
'name': 'A'
},
{
'id': 2,
'parent_id': 101,
'name': 'B'
},
{
'id': 3,
'parent_id': 102,
'name': 'C'
},
{
'id': 4,
'parent_id': 102,
'name': 'D'
}
]
I want to convert this to a nested dictionary.
Structure:
{
parent_id_value: {
name_value: id_value
}
}
Result of the sample list of dictionary object should be like this
{
101: {
'A': 1,
'B': 2
},
102: {
'C': 3,
'D': 4
}
}
I know we can run a for loop and use setdefault to set/get paren_id value and then add the name and id as key, value
new_dic = {}
for i in data:
new_dic.setdefault(i['parent_id'], {})[i['name']] = i['id']
print(new_dic)
But I am looking for a more pythonic way, meaning is it possible through dictionary comprehension?
So you want to play the comprehension game and you want to see a pro player at it.
Forget about itertools, forget about multiple statements. Here is the ultimate comprehension that will make any programmer working on your code throw the keyboard away and leave the room cursing you.
data = {parent_id: {d["name"]: d["id"] for d in [i for i in data if i["parent_id"] == parent_id]} for parent_id in set((j["parent_id"] for j in data))}
But for real though, don't do this in your code if it's going to be shared with someone.
First, sort the list using operator.itemgetter to supply the key:
data.sort(key=itemgetter('parent_id'))
Then use itertools.groupby to group the intended sections in a nested dict-comprehension:
data = {
key: {item['name']: item['id'] for item in group}
for key, group in groupby(data, itemgetter('parent_id'))
}
I don't recommend writing a one-liner, but you can do it with sorted:
data = {
key: {item['name']: item['id'] for item in group}
for key, group in groupby(sorted(data, key=itemgetter('parent_id')), itemgetter('parent_id'))
}

Compare two dictionary lists, based on specific key

I'll try to be the more concise that I can.
Two dictionary lists as follows:
dictlist1 = [{'name': 'john', 'age': 30}, {'name': 'jessica', 'age': 56}, {'name': 'kirk', 'age': 20}, {'name': 'mario, 'age': 25}]
dictlist2 = [{'name': 'john', 'job': 'engineer'}, {'name': 'jessica', 'job':'nurse'}, {'name': 'mario', 'job': 'electrician'}]
My objective is to match base on the key "name" on both dictionaries and, at the end, create a third dictionary list with the key that has no match, in this case {'name':'kirk' , 'age':20}, like this:
listfinal = [{'name': 'kirk', 'age': 20}]
I've tried successfully compare the equal keys, creating a new dictionary with keys that matches and adding "job" key to it, doing this:
for dict2 in dictlist2:
for dict1 in dictlist1:
if dict1['name'] == dict2['name']:
matchname1 = dict2['name']
dictoutput = {'name': matchname1, 'age': dict1['age'], 'group': dict2['group']}
templist.append(dictoutput)
for dictionay in templist:
print(dictionay)
Output:
{'name': 'john', 'age': '30', 'job': 'engineer'}
{'name': 'jessica', 'age': '56', 'job': 'nurse'}
{'name': 'mario', 'age': '25', 'job': 'electrician'}
But absolutely no luck to get kirk user alone, not even using "else" in the inner if statement or creating a new if statement and using not equal (!=). I always get all the users when printing.
Any orientation will be highly appreciated.
Enumerate the lists and then collect the indices of matched pairs in a list inside the loop and delete corresponding elements outside the loop.
matched_d1 = []
matched_d2 = []
for j2, dict2 in enumerate(dictlist2):
for j1, dict1 in enumerate(dictlist1):
if dict1['name'] == dict2['name']:
matchname1 = dict2['name']
dictoutput = {'name': matchname1, 'age': dict1['age'], 'group': dict2['group']}
templist.append(dictoutput)
matched_d1.append(j1)
matched_d2.append(j2)
for j in sorted(matched_d1, reverse = True):
dictlist1.pop(j)
for j in sorted(matched_d2, reverse = True):
dictlist2.pop(j)
ans = dictlist1 + dictlist2
You can use sets to find the names that are only in dictlist1, in dictlist2 and also the common names. Then create the listfinal by keeping only the item with the name not in the common names:
dictlist1 = [{"name": "john", "age": 30}, {"name": "jessica", "age": 56}, {"name":"kirk" , "age": 20}, {"name": "mario", "age": 25}]
dictlist2 = [{"name": "john", "job": "engineer"}, {"name": "jessica", "job": "nurse"}, {"name": "mario", "job": "electrician"}]
names_dictlist1 = {item["name"] for item in dictlist1}
names_dictlist2 = {item["name"] for item in dictlist2}
common_names = names_dictlist1 & names_dictlist2
listfinal = [item for item in dictlist1 + dictlist2 if item["name"] not in common_names]
If you want one-line solution there it is
print([person for person in dictlist1 if person['name'] not in map(lambda x: x['name'], dictlist2)])
This code prints element from fist list wich "name" key doesnt occur in second list
you can use set operations to get the unique name, first make a set of the names on each one and subtract both, then use that to get the appropriate item form the list
>>> name1 = set(d["name"] for d in dictlist1)
>>> name2 = set(d["name"] for d in dictlist2)
>>> name1 - name2
{'kirk'}
>>> name2 - name1
set()
>>> unique = name1 - name2
>>> listfinal = [d for n in unique for d in dictlist1 if d["name"]==n]
>>> listfinal
[{'name': 'kirk', 'age': 20}]
>>>
Additionally, looking at #freude answers, you can make it a dictionary of name:index for each list an subtracts its keys, given that they dict.keys behave set-like in order to avoid a double loop from before to get the right item from the list
>>> name1 = {d["name"]:i for i,d in enumerate(dictlist1)}
>>> name2 = {d["name"]:i for i,d in enumerate(dictlist2)}
>>> unique = name1.keys() - name2.keys()
>>> unique
{'kirk'}
>>> [ dictlist1[name1[n]] for n in unique]
[{'name': 'kirk', 'age': 20}]
>>>

Python : Find in an array of dict the element that match partially another dict

I have a dict myDict that look like this :
{
'score': 1,
'surname': 'AA AA',
'name': 'AAA AAA'
}
And I have an array of dict myArray that look like this :
[
{
'score': 0.9,
'surname': 'AA AA',
'name': 'AAA AAA'
},
{
'score': 0.6,
'surname': 'BB BB',
'name': 'BBB BBB'
},
...
]
I am looking for a function that will find in myArray, the element that have the same name and surname that myDict, and return the score.
Is there a way to achieve this without manualy itering over myArray ?
You can also just iterate through myArray with smth like this:
def find_score(myDict, myArray):
name, surname = myDict['name'], myDict['surname']
for i in myArray:
if i['name'] == name and i['surname'] == surname:
return i['score']
You can use a list comprehension, like this:
ls=[d for d in myArray if d["surname"]==myDict["surname"] and d["name"]==myDict["name"]]
This will give you a list of all dictionaries in myArray that match name and surname in myDict. If there will always only be one such value, you can retrieve the score with ls[0]["score"].
Not though, that while list comprehensions are neat and compact Pythonic ways to do things, technically you are still iterating over myArray.
Otherwise you could consider converting myArray to a Pandas DataFrame and using it's built-in filtering functions.

Fetching nested value given dot notation

I have the following structure in my json:
obj = {
'Name': 'David',
'Car': {
'Make': 'Ford',
'Year': 2008
}
}
I am given dot notation to refer to the object value, for example:
Car.Make ==> 'Form'
Given a string, such as "Car.Make", how would I programmatically fetch the attribute? In the above example, it would be:
obj.get('Car').get('Make')
But what about for a deeply-nested object, how would I extract the value given dot notation of "Attr1.Attr2.Attr3...Attrn" ?
obj = {
'Name': 'David',
'Car': {
'Make': 'Ford',
'Year': 2008
}
}
s = "Car.Make"
x = obj
keys = s.split(".")
for key in keys:
x = x[key]
print(x)
Result:
Ford
Or, in one-liner form:
from functools import reduce
print(reduce(lambda a,b: a[b], s.split("."), obj))
Here are some answers from Stackoverflow that propose a custom dictionary class that implements __getattr__ and __setattr__ to access the dictionary items:
How to use a dot "." to access members of dictionary?
Accessing dict keys like an attribute in Python?

Categories

Resources