Assuming the following dictionary in Python:
original_dict = {'place_01': 'Tom',
'place_02': 'John',
'place_03': 'Steve',
'place_04': 'Mark'}
I would like to define a function that allows me to exchange a defined pair values list.
My function should look like:
def change_position(mydict, change_from, change_to):
Passing the following arguments:
new_dict = change_position(original_dict, ['Tom','John'], ['Mark','Steve'])
Desidered result should be:
new_dict = {'place_01': 'Mark',
'place_02': 'Steve',
'place_03': 'John',
'place_04': 'Tom'}
basically:
'Tom' has been exchanged with 'Mark'
'John' has been exchanged Steve)
You can use a dictionary comprehension:
def change_position(mydict, c1, c2):
d = {**dict(zip(c1, c2)), **dict(zip(c2, c1))}
return {a:d[b] for a, b in mydict.items()}
original_dict = {'place_01': 'Tom', 'place_02': 'John', 'place_03': 'Steve', 'place_04': 'Mark'}
result = change_position(original_dict, ['Tom', 'John'], ['Mark', 'Steve'])
Output:
{'place_01': 'Mark', 'place_02': 'Steve', 'place_03': 'John', 'place_04': 'Tom'}
Requirement: values being unique in the dict
You need
a copy of my_dict to apply the changes
a reversed dict value > key to know where to apply the changes
Then iterate and swap
def change_position(mydict, change_from, change_to):
result = {**mydict}
mappings = {v: k for k, v in mydict.items()}
for val_from, val_to in zip(change_from, change_to):
key_from, key_to = mappings[val_from], mappings[val_to]
result[key_to], result[key_from] = mydict[key_from], mydict[key_to]
return result
Gives
original_dict = {'place_01': 'Tom', 'place_02': 'John', 'place_03': 'Steve', 'place_04': 'Mark'}
new_dict = change_position(original_dict, ['Tom', 'John'], ['Mark', 'Steve'])
print(new_dict) # {'place_01': 'Mark', 'place_02': 'Steve', 'place_03': 'John', 'place_04': 'Tom'}
Related
I have a dict as follows.
dict = {'P': ['Demo'], 'Q': ['PMS']}
And I have a list of Dict as follows.
all = [{'Name': 'PMS'}, {'Name': 'Demo'}]
I need to have the dict's respective value in all as bellow.
new_list = [{'Name': 'PMS','Code': 'Q'}, {'Name': 'Demo','Code': 'P'}]
In this specific case, given that the values are just strings and therefore hashable objects, you can use a dictionary of reverse mappings. Be aware that it could not be used if the values were not hashable.
dct = {'P': ['Demo'], 'Q': ['PMS']}
all = [{'Name': 'PMS'}, {'Name': 'Demo'}]
reverse_mapping = {v[0]:k for k, v in dct.items()}
new_list = [d.copy() for d in all]
for d in new_list:
d['Code'] = reverse_mapping[d['Name']]
print(new_list)
This gives:
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
dct = {'P': ['Demo'], 'Q': ['PMS']}
all_ = [{'Name': 'PMS'}, {'Name': 'Demo'}]
out = [dict(**l, Code=next(k for k, v in dct.items() if l['Name'] in v)) for l in all_]
print(out)
Prints:
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
Or: you can make temporary dictionary:
tmp = {v[0]:k for k, v in dct.items()}
out = [dict(**l, Code=tmp[l['Name']]) for l in all_]
print(out)
You could make an inverted dictionary of codes, then go through the list of dictionaries and add the codes in:
codes = {"P": ["Demo"], "Q": ["PMS"]}
lst = [{"Name": "PMS"}, {"Name": "Demo"}]
inverted_codes = {value: key for key, values in codes.items() for value in values}
# {'Demo': 'P', 'PMS': 'Q'}
for dic in lst:
code = dic["Name"]
dic["Code"] = inverted_codes[code]
print(lst)
Output
[{'Name': 'PMS', 'Code': 'Q'}, {'Name': 'Demo', 'Code': 'P'}]
I have a list of dictionaries that looks like the following:
data = [{'Name': 'Paul', 'Date': '20200412', 'ID': '1020'}, {'Name': 'Frank', 'Date': '20200413', 'ID': '1030'}, {'Name': 'Anna', 'Date': '20200414', 'ID': '1040'}]
I need to create a new list of dictionaries, where ID's value would be the key, and the value is another dictionary with key/values associated with this specific ID.
This is the desired output:
new_data = [{'1020': {'Name': 'Paul', 'Date': '20200412'}},
{'1030': {'Name': 'Frank', 'Date': '20200413'}},
{'1040': {'Name': 'Anna', 'Date': '20200414'}}]
I have tried:
for index, my_dict in enumerate(data):
new_data = []
key = my_dict['ID']
new_data.append(key)
But that only assigned the key value, not sure how to push it into into a new dict along with other key/values.
>>> [{i['ID']: {k:v for k,v in i.items() if k != 'ID'}} for i in data]
[{'1020': {'Name': 'Paul', 'Date': '20200412'}},
{'1030': {'Name': 'Frank', 'Date': '20200413'}},
{'1040': {'Name': 'Anna', 'Date': '20200414'}}]
new_data = []
for index, my_dict in enumerate(data):
key = my_dict['ID']
del my_dict['ID']
new_data.append({key:data[index]})
To add the other values you simply need to create a new dict like this:
new_data.append( key:{
'name':my_dict['name']
'Date':my_dict['date']
}
You also don't need to make the 'key' variable, you can just use 'my_dict['ID']'
You could try this list comprehension:
[{x["ID"]: {k: v for k, v in x.items() if k != "ID"}} for x in data]
Which assigns ID as the parent key to the dictionary, and filters out the ID key from the child dictionary inside a dict comprehension
Which could be broken down into this:
result = []
for x in data:
result.append({x["ID"]: {k: v for k, v in x.items() if k != "ID"}})
And even to a straightforward loop approach:
result = []
for x in data:
dic = {x["ID"]: {}}
for k, v in x.items():
if k != "ID":
dic[x["ID"]][k] = v
result.append(dic)
Output:
[{'1020': {'Name': 'Paul', 'Date': '20200412'}}, {'1030': {'Name': 'Frank', 'Date': '20200413'}}, {'1040': {'Name': 'Anna', 'Date': '20200414'}}]
My solution
keys = ['FirstName', 'LastName', 'ID']
name1 = ['Michael', 'Jordan', '224567']
name2 = ['Kyle', 'Hynes', '294007']
name3 = ['Josef', 'Jones', '391107']
dictList = []
dictList.append(dict(zip(keys, name1)))
dictList.append(dict(zip(keys, name2)))
dictList.append(dict(zip(keys, name3)))
Works fine, but is there any other solution, because I will have at least 20000 names, so I am looking how to improve this.
Place all your "name" sublists into the parent list names. Then you can easily use list comprehension:
keys = ['FirstName', 'LastName', 'ID']
names = [
['Michael', 'Jordan', '224567'],
['Kyle', 'Hynes', '294007'],
['Josef', 'Jones', '391107']
]
dictList = [{k:v for k,v in zip(keys, n)} for n in names]
print(dictList)
The output:
[{'FirstName': 'Michael', 'LastName': 'Jordan', 'ID': '224567'}, {'FirstName': 'Kyle', 'LastName': 'Hynes', 'ID': '294007'}, {'FirstName': 'Josef', 'LastName': 'Jones', 'ID': '391107'}]
Do you really need a dictionary? Why not just use a namedtuple:
>>> from collections import namedtuple
>>> Employee = namedtuple('Employee', 'FirstName, LastName, ID')
>>> names_list = [['Michael', 'Jordan', '224567'], ['Kyle', 'Hynes', '294007'], ['Josef', 'Jones', '391107']]
>>> employee_list = map(Employee._make, names_list)
>>> employee_list[0].FirstName
'Michael'
>>> pprint(employee_list)
[Employee(FirstName='Michael', LastName='Jordan', ID='224567'),
Employee(FirstName='Kyle', LastName='Hynes', ID='294007'),
Employee(FirstName='Josef', LastName='Jones', ID='391107')]
pandas makes this too easy.
import pandas as pd
keys = ['FirstName', 'LastName', 'ID']
name1 = ['Michael', 'Jordan', '224567']
name2 = ['Kyle', 'Hynes', '294007']
name3 = ['Josef', 'Jones', '391107']
doc_list = [name1,name2,name3]
df = pd.DataFrame(doc_list,columns = keys)
So you'll have a DataFrame like this:
FirstName LastName ID
0 Michael Jordan 224567
1 Kyle Hynes 294007
2 Josef Jones 391107
If your names are already in a file,read_csv would be better.
pd.read_csv("file_name.csv",header=keys)//remove the header parameter if it is present in your csv.
You should append your dictionaries to the list inside a loop, like this:
In [1152]: names = [name1, name2, name3]
In [1153]: d = []
In [1154]: for name in names:
...: d.append(dict(zip(keys, name)))
...:
In [1155]: d
Out[1155]:
[{'FirstName': 'Michael', 'ID': '224567', 'LastName': 'Jordan'},
{'FirstName': 'Kyle', 'ID': '294007', 'LastName': 'Hynes'},
{'FirstName': 'Josef', 'ID': '391107', 'LastName': 'Jones'}]
Or, if you prefer, a list comprehension:
In [1160]: d = [dict(zip(keys, name)) for name in names]
In [1161]: d
Out[1161]:
[{'FirstName': 'Michael', 'ID': '224567', 'LastName': 'Jordan'},
{'FirstName': 'Kyle', 'ID': '294007', 'LastName': 'Hynes'},
{'FirstName': 'Josef', 'ID': '391107', 'LastName': 'Jones'}]
I can't get my head around this problem:
I have a List:
[{'name' : 'Bob', 'Salary2014' : 2000}, {'name': 'Alice', 'Salary2014' : 1000}, {'name':'Bob', 'Salary2013' : 1500}]
I want to join the dictionarys on base of the Name (which is unique)
[{'name' : 'Bob', 'Salary2014' : 2000, 'Salary2013' : 1500}, {'name': 'Alice', 'Salary2014' : 1000}]
I know the solution has to be simple and may involve the .update method, but I just don't get it.
Use a new dictionary to track your dictionaries based on name:
combined = {}
for d in yourlist:
combined.setdefault(d['name'], {}).update(d)
output = combined.values()
The combined.setdefault() method here sets {} as a default value if d['name'] is not present, then updates the dictionary with the current iteration.
If you are using Python 3, use list(combined.values()).
Demo:
>>> yourlist = [{'name' : 'Bob', 'Salary2014' : 2000}, {'name': 'Alice', 'Salary2014' : 1000}, {'name':'Bob', 'Salary2013' : 1500}]
>>> combined = {}
>>> for d in yourlist:
... combined.setdefault(d['name'], {}).update(d)
...
>>> combined.values()
[{'Salary2013': 1500, 'name': 'Bob', 'Salary2014': 2000}, {'name': 'Alice', 'Salary2014': 1000}]
The other pretty similar way is to use defaultdict:
from collections import defaultdict
inp = [{'name': 'Bob', 'Salary2014': 2000},
{'name': 'Alice', 'Salary2014': 1000},
{'name': 'Bob', 'Salary2013': 1500}]
out = defaultdict(dict)
for rec in inp:
out[rec['name']].update(rec)
print out.values()
Learning about Python's zip function. I can do this
list_keys = ['fname','lname','dob']
list_data = ['bob','smith','12121950']
keys_and_data = dict(zip(list_keys,list_data))
print keys_and_data
#output
{'lname': 'smith', 'dob': '12121950', 'fname': 'bob'}
Now I am trying to figure out how to get this to work
list_keys = ['fname','lname','dob']
list_data = [['bob','smith','12121950'],['john','jones','10101940']]
keys_and_data = ??
print keys_and_data
#output
{['lname': 'smith', 'dob': '12121950', 'fname': 'bob'],
['lname': 'jones', 'dob': '10101940', 'fname': 'john']}
How do I get python to repeat the keys?
Loop over list_data in a list comprehension:
keys_and_data = [dict(zip(list_keys, data)) for data in list_data]
Demo:
>>> list_keys = ['fname','lname','dob']
>>> list_data = [['bob','smith','12121950'],['john','jones','10101940']]
>>> [dict(zip(list_keys, data)) for data in list_data]
[{'lname': 'smith', 'dob': '12121950', 'fname': 'bob'}, {'lname': 'jones', 'dob': '10101940', 'fname': 'john'}]