How to order the keys of Dictionary - python

I have the below dictionary and I would like to print the keys in the order:
[Name,Gender,Occupation,Location]
{'Gender': 'Male',
'Location': 'Nizampet,Hyderabad',
'Name': 'Srikanth',
'Occupation': 'Data Scientist'}
Can someone suggest how it can be done.

You can arrange the order of keys when you create the dictionary.
Python 3.7+
In Python 3.7.0 the insertion-order preservation nature of
dict objects has been declared to be an official part of the Python
language spec. Therefore, you can depend on it.
old_dict = {'Gender': 'Male', 'Location': 'Nizampet,Hyderabad', 'Name': 'Srikanth', 'Occupation': 'Data Scientist'}
new_dict = {
"Name": old_dict["Name"],
"Gender": old_dict["Gender"],
"Occupation": old_dict["Occupation"],
"Location": old_dict["Location"]
}
print(new_dict)
Output
{'Name': 'Srikanth', 'Gender': 'Male', 'Occupation': 'Data Scientist', 'Location': 'Nizampet,Hyderabad'}

If you have a predetermined order in which you'd like to print the data, store the order in a list of keys and loop through them.
data = {
'Gender': 'Male',
'Location': 'Nizampet,Hyderabad',
'Name': 'Srikanth',
'Occupation': 'Data Scientist'
}
print_order = [
'Name',
'Gender',
'Occupation',
'Location',
]
for key in print_order:
print(f'{key}: {data[key]}')
Output:
$ python3 print_dict_in_order.py
Name: Srikanth
Gender: Male
Occupation: Data Scientist
Location: Nizampet,Hyderabad

Related

Restrict adding bad entry to python dictionary?

We have sample Python dictionary as given below, which can be modify by multiple developers in our project.
What could be best way to avoid developers not to add other than given sample keys, also to avoid them to add incorrect zip entry in address of person( zip should validate through post codes then allow to add zip), etc. also there is no currency exists with 'AAA' its invalid key, also having invalid value, I think we can do it with special functions dict.add dict.key is there any other best way to do it.
people = {1: {'name': 'John', 'age': '27', 'sex': 'Male', 'Address': { 'Door': '9-8-11', 'street': 'John-street', 'city': 'NewYork', 'zip':'99705'}, 'ExchangeCurrency':{'USD':'INR'}},
2: {'name': 'Marie', 'age': '22', 'sex': 'Female', 'Address': { 'Door': '9-8-11', 'street': 'John-street', 'city': 'NewYork', 'zip': '99705'}, 'ExchangeCurrency':{'INR':'EUR'}}}
Eg of bad entry:
{1: {'name12': 'John', 'age': '27', 'sex': 'Male', 'Address': { 'Door': '9-8-11', 'street': 'John-street', 'city': 'NewYork', 'zip':'000000'}, 'ExchangeCurrency':{'AAA':'CCC'}}
One approach that you might want to consider is creating your own class for each of the people for which the "given sample keys" (e.g. name, age, sex, and address) are object attributes and keyword arguments to the initialization function. For instance, you could do the following.
class Person(object):
def __init__(self, name = '', age = '0', sex = None, address = {}):
self.name = name
self.age = age
self.sex = sex
self.address = address
With that, you can enter person one into the system with
person_1 = Person(name = 'John',
age = '27',
sex = 'Male',
address = { 'Door': '9-8-11', 'street': 'John-street', 'city': 'NewYork', 'zip':'99705'})
In fact, you can very nicely unpack your dictionary version of a person to create this a Person instance. For example, we can change your dictionary of dictionaries to a dictionary of Person objects as follows.
people_dic_1 = {1: {'name': 'John', 'age': '27', 'sex': 'Male', 'address': { 'door': '9-8-11', 'street': 'John-street', 'city': 'NewYork', 'zip':'99705'}},
2: {'name': 'Marie', 'age': '22', 'sex': 'Female', 'address': { 'door': '9-8-11', 'street': 'John-street', 'city': 'NewYork', 'zip': '99705'}}}
people_dic_2 = {k:Person(**v) for k,v in people_dic.items()}
In the above, Person(**v) is a person object with attributes determined by the dictionary v. Notably, calling Person(**v) will only work if each key corresponds to a (correctly named) keyword argument of the __init__ method.
To go the other direction, you can call vars on a Person object to produce the kind of dictionary that you've been using. For instance, calling vars(people_dic_2[2]) after running the above code yields the dictionary
{'name': 'Marie',
'age': '22',
'sex': 'Female',
'address': {'door': '9-8-11',
'street': 'John-street',
'city': 'NewYork',
'zip': '99705'}}
You could similarly create a class for addresses, if you're so inclined.

Creating json for special values in the dict of dicts python

I have dictionary like that:
dic={'61': {'NAME': 'John', 'LASTNAME': 'X', 'EMAIL': 'X#example.com', 'GRADE': '99'}, '52': {'NAME': 'Jennifer', 'LASTNAME': 'Y', 'EMAIL': 'Y#example.com', 'GRADE': '98'}}
obj = json.dumps(dic,indent=3)
print(obj)
I want to create Json for some values.
{
"NAME": "John",
"LASTNAME": "X",
,
"NAME": "Jennifer",
"LASTNAME": "Y"
}
Any idea for help?
If I understand correctly you want to keep the values of your original data without the indices and also filter out some of them (keep only "NAME" and "LASTNAME"). You can do so by using a combination of dictionary and list comprehensions:
array = [{k:v for k,v in d.items()if k in ("NAME","LASTNAME")} for d in dic.values()]
This creates the following output:
>>> array
[{'NAME': 'John', 'LASTNAME': 'X'}, {'NAME': 'Jennifer', 'LASTNAME': 'Y'}]

How to check if specific keys and values are also in a dictionary?

The following is a subset of a nested dictionary that I have:
data = {
'1': {'Address': '10/3 Beevers St',
'Age': '27',
'Job': 'Doctor',
'Married': 'No',
'Name': 'John',
'Sex': 'Male',
'Suburb': 'Marine'},
'2': {'Address': '11/2 Sayers St',
'Age': '22',
'Job': 'Lawyer',
'Married': 'Yes',
'Name': 'Marie',
'Sex': 'Female',
'Suburb': 'Raffles'},
'3': {'Address': '5/1 Swamphen St',
'Age': '24',
'Job': 'Manager',
'Married': 'No',
'Name': 'Luna',
'Sex': 'Female',
'Suburb': 'Eunos'},
'4': {'Address': '25/12 Swamphen St',
'Age': '35',
'Job': 'Teacher',
'Married': 'Yes',
'Name': 'Larry',
'Sex': 'Male',
'Suburb': 'Eunos'}
}
And here is a JSON string:
json_str = '[{"Suburb": "Marine", "Address": "3 Beevers St"},\
{"Suburb": "Raffles", "Address": "11/2 Sayers St"},\
{"Suburb": "Eunos", "Address": "Swamphen St"}]'
My task is to check if a house ("Suburb" and "Address") in json_str is also in the original dataset (nested dictionary called data). If it is, then add the key/value for 'Age' and 'Name' to the JSON string for that house.
The output looks something like this:
[{'Age': 27,
'Address': '10/3 Beevers St',
'Name': 'John',
'Suburb': 'Marine'},
{'Age': 22,
'Address': '11/2 Sayers St',
'Name': 'Marie',
'Suburb': 'Raffles'}]
Thus, I was wondering if I can get some help on how to approach this question? I have tried writing out a code, but I keep getting errors, so I believe my approach is very incorrect...
def add_additional_info(data, json_str):
python_dict = json.loads(json_str)
new_dict = {}
for some_id, sales_data in data.items():
for houses in python_dict:
if houses["Suburb"] == sales_data["Suburb"] and \
houses["Address"] == sales_data["Address"]:
new_dict[houses] = {'Age': sales_data['Age'],
'Address': sales_data['Address'],
'Name': sales_data['Name'],
'Suburb': sales_data['Suburb']}
else:
new_dict.remove(houses)
return new_dict.dumps
I think this does what you said you want, include the clarifications you mentioned in comments about ignoring duplicate matches and the specified ordering of the keys in the results.
First, the test data:
data = {
'1': {'Address': '10/3 Beevers St',
'Age': '27',
'Job': 'Doctor',
'Married': 'No',
'Name': 'John',
'Sex': 'Male',
'Suburb': 'Marine'},
'2': {'Address': '11/2 Sayers St',
'Age': '22',
'Job': 'Lawyer',
'Married': 'Yes',
'Name': 'Marie',
'Sex': 'Female',
'Suburb': 'Raffles'},
'3': {'Address': '5/1 Swamphen St',
'Age': '24',
'Job': 'Manager',
'Married': 'No',
'Name': 'Luna',
'Sex': 'Female',
'Suburb': 'Eunos'},
'4': {'Address': '25/12 Swamphen St',
'Age': '35',
'Job': 'Teacher',
'Married': 'Yes',
'Name': 'Larry',
'Sex': 'Male',
'Suburb': 'Eunos'}
}
json_str = '''[{"Suburb": "Marine", "Address": "3 Beevers St"},
{"Suburb": "Raffles", "Address": "11/2 Sayers St"},
{"Suburb": "Eunos", "Address": "Swamphen St"}]'''
The code:
SUBSET = 'Age', 'Address', 'Name', 'Suburb' # Keys from data to put in result.
def add_additional_info(data, json_str):
houses = json.loads(json_str)
updated_houses = []
for house in houses:
# Search original dataset for house and add it to results, but only if
# there's a single match.
found = None
for some_id, sales_data in data.items():
if(house["Suburb"] == sales_data["Suburb"] and
house["Address"] in sales_data["Address"]): # Might ignore unit number.
if not found: # First match?
found = {key: sales_data[key] for key in SUBSET}
else:
found = None # Ignore multiple matches.
break # Halt search for house.
if found:
updated_houses.append(found)
return json.dumps(updated_houses, indent=4)
result = add_additional_info(data, json_str)
print(result)
Printed results:
[
{
"Age": "27",
"Address": "10/3 Beevers St",
"Name": "John",
"Suburb": "Marine"
},
{
"Age": "22",
"Address": "11/2 Sayers St",
"Name": "Marie",
"Suburb": "Raffles"
}
]
The way you're doing it now is comparing the complete dict entry for the JSON data with the complete dict entry of the other data. This will never match as these have separate keys, so the dicts are by defenition different.
You need to compare exact keys for both dict entries, fe:
if houses['Address'] == sales_data['Address'] and houses['Suburb'] == sales_data['Suburb']:
Also, never delete entries from a dict you are looping through. This leads to weird results. Create a new dict to which you add the ones you need to return, and add the matching entries to that.

Filter python dictionary with dictionary-comprehension

I have a dictionary that is really a geojson:
points = {
'crs': {'properties': {'name': 'urn:ogc:def:crs:OGC:1.3:CRS84'}, 'type': 'name'},
'features': [
{'geometry': {
'coordinates':[[[-3.693162104185235, 40.40734504903418],
[-3.69320229317164, 40.40719570724241],
[-3.693227952841606, 40.40698546120488],
[-3.693677594635894, 40.40712700492216]]],
'type': 'Polygon'},
'properties': {
'name': 'place1',
'temp': 28},
'type': 'Feature'
},
{'geometry': {
'coordinates': [[[-3.703886381691941, 40.405197271972035],
[-3.702972834622821, 40.40506272989243],
[-3.702552994966045, 40.40506798079752],
[-3.700985024825222, 40.405500820623814]]],
'type': 'Polygon'},
'properties': {
'name': 'place2',
'temp': 27},
'type': 'Feature'
},
{'geometry': {
'coordinates': [[[-3.703886381691941, 40.405197271972035],
[-3.702972834622821, 40.40506272989243],
[-3.702552994966045, 40.40506798079752],
[-3.700985024825222, 40.405500820623814]]],
'type': 'Polygon'},
'properties': {
'name': 'place',
'temp': 25},
'type': 'Feature'
}
],
'type': u'FeatureCollection'
}
I would like to filter it to stay only with places that have a specific temperature, for example, more than 25 degrees Celsius.
I have managed to do it this way:
dict(crs = points["crs"],
features = [i for i in points["features"] if i["properties"]["temp"] > 25],
type = points["type"])
But I wondered if there was any way to do it more directly, with dictionary comprehension.
Thank you very much.
I'm very late. A dict compreheneison won't help you since you have only three keys. But if you meet the following conditions: 1. you don't need a copy of features (e.g. your dict is read only); 2. you don't need index access to features, you my use a generator comprehension instead of a list comprehension:
dict(crs = points["crs"],
features = (i for i in points["features"] if i["properties"]["temp"] > 25),
type = points["type"])
The generator is created in constant time, while the list comprehension is created in O(n). Furthermore, if you create a lot of those dicts, you have only one copy of the features in memory.

Merging similar dictionaries in a list together

New to python here. I've been pulling my hair for hours and still can't figure this out.
I have a list of dictionaries:
[ {'FX0XST001.MID5': '195', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'}
{'FX0XST001.MID13': '4929', 'Name': 'Firmicutes', 'Taxonomy ID': '1239','Type': 'phylum'},
{'FX0XST001.MID6': '826', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'},
.
.
.
.
{'FX0XST001.MID6': '125', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'}
{'FX0XST001.MID25': '70', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'}
{'FX0XST001.MID40': '40', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'} ]
I want to merge the dictionaries in the list based on their Type, Name, and Taxonomy ID
[ {'FX0XST001.MID5': '195', 'FX0XST001.MID13': '4929', 'FX0XST001.MID6': '826', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'}
.
.
.
.
{'FX0XST001.MID6': '125', 'FX0XST001.MID25': '70', 'FX0XST001.MID40': '40', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'}]
I have the data structure setup like this because I need to write the data to CSV using csv.DictWriter later.
Would anyone kindly point me to the right direction?
You can use the groupby function for this:
http://docs.python.org/library/itertools.html#itertools.groupby
from itertools import groupby
keyfunc = lambda row : (row['Type'], row['Taxonomy ID'], row['Name'])
result = []
data = sorted(data, key=keyfunc)
for k, g in groupby(data, keyfunc):
# you can either add the matching rows to the item so you end up with what you wanted
item = {}
for row in g:
item.update(row)
result.append(item)
# or you could just add the matched rows as subitems to a parent dictionary
# which might come in handy if you need to work with just the parts that are
# different
item = {'Type': k[0], 'Taxonomy ID' : k[1], 'Name' : k[2], 'matches': [])
for row in g:
del row['Type']
del row['Taxonomy ID']
del row['Name']
item['matches'].append(row)
result.append(item)
Make some test data:
list_of_dicts = [
{"Taxonomy ID":1, "Name":"Bob", "Type":"M", "hair":"brown", "eyes":"green"},
{"Taxonomy ID":1, "Name":"Bob", "Type":"M", "height":"6'2''", "weight":200},
{"Taxonomy ID":2, "Name":"Alice", "Type":"F", "hair":"black", "eyes":"hazel"},
{"Taxonomy ID":2, "Name":"Alice", "Type":"F", "height":"5'7''", "weight":145}
]
I think this (below) is a neat trick using reduce that improves upon the other groupby solution.
import itertools
def key_func(elem):
return (elem["Taxonomy ID"], elem["Name"], elem["Type"])
output_list_of_dicts = [reduce((lambda x,y: x.update(y) or x), list(val)) for key, val in itertools.groupby(list_of_dicts, key_func)]
Then print the output:
for elem in output_list_of_dicts:
print elem
This prints:
{'eyes': 'green', 'Name': 'Bob', 'weight': 200, 'Taxonomy ID': 1, 'hair': 'brown', 'height': "6'2''", 'Type': 'M'}
{'eyes': 'hazel', 'Name': 'Alice', 'weight': 145, 'Taxonomy ID': 2, 'hair': 'black', 'height': "5'7''", 'Type': 'F'}
FYI, Python Pandas is far better for this sort of aggregation, especially when dealing with file I/O to .csv or .h5 files, than the itertools stuff.
Perhaps the easiest thing to do would be to create a new dictionary, indexed by a (Type, Name, Taxonomy ID) tuple, and iterate over your dictionary, storing values by (Type, Name, Taxonomy ID). Use a default dict to make this easier. For example:
from collections import defaultdict
grouped = defaultdict(lambda : {})
# iterate over items and store:
for entry in list_of_dictionaries:
grouped[(entry["Type"], entry["Name"], entry["Taxonomy ID"])].update(entry)
# now you have everything stored the way you want in values, and you don't
# need the dict anymore
grouped_entries = grouped.values()
This is a bit hackish, especially because you end up overwriting "Type", "Name", and "Phylum" every time you use update, but since your dict keys are variable, that might be the best you can do. This will get you at least close to what you need.
Even better would be to do this on your initial import and skip intermediate steps (unless you actually need to transform the data beforehand). Plus, if you could get at the only varying field, you could change the update to just: grouped[(type, name, taxonomy_id)][key] = value where key and value are something like: 'FX0XST001.MID5', '195'
from itertools import groupby
data = [ {'FX0XST001.MID5': '195', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type':'phylum'},
{'FX0XST001.MID13': '4929', 'Name': 'Firmicutes', 'Taxonomy ID': '1239','Type': 'phylum'},
{'FX0XST001.MID6': '826', 'Name': 'Firmicutes', 'Taxonomy ID': '1239', 'Type': 'phylum'},
{'FX0XST001.MID6': '125', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'},
{'FX0XST001.MID25': '70', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'},
{'FX0XST001.MID40': '40', 'Name': 'Acidobacteria', 'Taxonomy ID': '57723', 'Type': 'phylum'} ,]
kk = ('Name', 'Taxonomy ID', 'Type')
def key(item): return tuple(item[k] for k in kk)
result = []
data = sorted(data, key=key)
for k, g in groupby(data, key):
result.append(dict((i, j) for d in g for i,j in d.items()))
print result

Categories