how to insert list of elements into list of dictionaries - python

I have one list of elements and another list of dictionaries and i want to insert list of elements into each dictionary of list
list_elem = [1,2,3]
dict_ele = [{"Name":"Madhu","Age":25},{"Name":"Raju","Age:24},{""Name":"Mani","Age":12}],
OUTPUT As:
[{"ID":1,"Name":"Madhu","Age":25},{"ID":2,"Name":"Raju","Age:24},{"ID":3,"Name":"Mani","Age":12}]
I have tried this way :
dit = [{"id":item[0]} for item in zip(sam)]
# [{"id":1,"id":2,"id":3}]
dic1 = list(zip(dit,data))
print(dic1)
# [({"id":1},{{"Name":"Madhu","Age":25}},{"id":2},{"Name":"Raju","Age:24},{"id":3},{""Name":"Mani","Age":12})]
What is the most efficient way to do this in Python?

Making an assumption here that the OP's original question has a typo in the definition of dict_ele and also that list_elem isn't really necessary.
dict_ele = [{"Name":"Madhu","Age":25},{"Name":"Raju","Age":24},{"Name":"Mani","Age":12}]
dit = [{'ID': id_, **d} for id_, d in enumerate(dict_ele, 1)]
print(dit)
Output:
[{'ID': 1, 'Name': 'Madhu', 'Age': 25}, {'ID': 2, 'Name': 'Raju', 'Age': 24}, {'ID': 3, 'Name': 'Mani', 'Age': 12}]

dict_ele = [{"Name":"Madhu","Age":25},{"Name":"Raju","Age":24},{"Name":"Mani","Age":12}]
list_elem = [1,2,3]
[{'ID': id, **_dict} for id, _dict in zip(list_elem, dict_ele)]
[{'ID': 1, 'Name': 'Madhu', 'Age': 25}, {'ID': 2, 'Name': 'Raju', 'Age': 24}, {'ID': 3, 'Name': 'Mani', 'Age': 12}]

try this: r = [{'id':e[0], **e[1]} for e in zip(list_elem, dict_ele)]

Related

Python, sort dict based on external list

I have to sort a dict like:
jobs = {'elem_05': {'id': 'fifth'},
'elem_03': {'id': 'third'},
'elem_01': {'id': 'first'},
'elem_00': {'id': 'zeroth'},
'elem_04': {'id': 'fourth'},
'elem_02': {'id': 'second'}}
based on the "id" elements, whose order can be found in a list:
sorting_list = ['zeroth', 'first', 'second', 'third', 'fourth', 'fifth']
The trivial way to solve the problem is to use:
tmp = {}
for x in sorting_list:
for k, v in jobs.items():
if v["id"] == x:
tmp.update({k: v})
but I was trying to figure out a more efficient and pythonic way.
I've been trying sorted and lambda functions as key, but I'm not familiar with that yet, so I was unsuccessful so far.
I would use a dictionary as key for sorted:
order = {k:i for i,k in enumerate(sorting_list)}
# {'zeroth': 0, 'first': 1, 'second': 2, 'third': 3, 'fourth': 4, 'fifth': 5}
out = dict(sorted(jobs.items(), key=lambda x: order.get(x[1].get('id'))))
output:
{'elem_00': {'id': 'zeroth'},
'elem_01': {'id': 'first'},
'elem_02': {'id': 'second'},
'elem_03': {'id': 'third'},
'elem_04': {'id': 'fourth'},
'elem_05': {'id': 'fifth'}}
There is a way to sort the dict using lambda as a sorting key:
jobs = {'elem_05': {'id': 'fifth'},
'elem_03': {'id': 'third'},
'elem_01': {'id': 'first'},
'elem_00': {'id': 'zeroth'},
'elem_04': {'id': 'fourth'},
'elem_02': {'id': 'second'}}
sorting_list = ['zeroth', 'first', 'second', 'third', 'fourth', 'fifth']
sorted_jobs = dict(sorted(jobs.items(), key=lambda x: sorting_list.index(x[1]['id'])))
print(sorted_jobs)
This outputs
{'elem_00': {'id': 'zeroth'}, 'elem_01': {'id': 'first'}, 'elem_02': {'id': 'second'}, 'elem_03': {'id': 'third'}, 'elem_04': {'id': 'fourth'}, 'elem_05': {'id': 'fifth'}}
I have a feeling the sorted expression could be cleaner but I didn't get it to work any other way.
You can use OrderedDict:
from collections import OrderedDict
sorted_jobs = OrderedDict([(el, jobs[key]['id']) for el, key in zip(sorting_list, jobs.keys())])
This creates an OrderedDict object which is pretty similar to dict, and can be converted to dict using dict(sorted_jobs).
Similar to what is already posted, but with error checking in case id doesn't appear in sorting_list
sorting_list = ['zeroth', 'first', 'second', 'third', 'fourth', 'fifth']
jobs = {'elem_05': {'id': 'fifth'},
'elem_03': {'id': 'third'},
'elem_01': {'id': 'first'},
'elem_00': {'id': 'zeroth'},
'elem_04': {'id': 'fourth'},
'elem_02': {'id': 'second'}}
def custom_order(item):
try:
return sorting_list.index(item[1]["id"])
except ValueError:
return len(sorting_list)
jobs_sorted = {k: v for k, v in sorted(jobs.items(), key=custom_order)}
print(jobs_sorted)
The sorted function costs O(n log n) in average time complexity. For a linear time complexity you can instead create a reverse mapping that maps each ID to the corresponding dict entry:
mapping = {d['id']: (k, d) for k, d in jobs.items()}
so that you can then construct a new dict by mapping sorting_list with the ID mapping above:
dict(map(mapping.get, sorting_list))
which, with your sample input, returns:
{'elem_00': {'id': 'zeroth'}, 'elem_01': {'id': 'first'}, 'elem_02': {'id': 'second'}, 'elem_03': {'id': 'third'}, 'elem_04': {'id': 'fourth'}, 'elem_05': {'id': 'fifth'}}
Demo: https://replit.com/#blhsing/WorseChartreuseFonts

Python str not list

I wanted to obtain array of int like [1,2,3]
but got [dict_values([1]),dict_values([2]),dict_values([3])]
My code:
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
taken_employee_ids = [str(taken_employee_ids_list.values()) for taken_employee_ids_list in taken_employee_ids_dict]
in_values_check = ','.join(str(id) for id in taken_employee_ids)
And then in_values_check should go in:
qry = "SELECT CONCAT(first_name, ',', surname) AS full_name, id \
FROM employees \
WHERE date_terminated IS NULL \
and id NOT IN " + "(" + in_values_check + ")" \
" ORDER BY first_name, surname ASC"
sorry i am new to python thanks
For a problem like this, a list comprehension is a commonly applied solution:
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
in_values_check = [employee["id"] for employee in taken_employee_ids_dict]
print(in_values_check)
This outputs
[1, 2, 3]
You can do it with lambda or list comprehension
With Lambda,
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
in_values_check = list(map(lambda x : x['id'], taken_employee_ids_dict))
print(in_values_check)
With List Comprehension,
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
in_values_check = [dic['id'] for dic in taken_employee_ids_dict]
print(in_values_check)
Output:
[1, 2, 3]
You can use something like this.
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
final_list = []
for ele in taken_employee_ids_dict:
for key,value in ele.items():
final_list.append(value)
print(final_list)
Try this:
taken_employee_ids = [str(employee["id"]) for employee in taken_employee_ids_dict]
in_values_check = ','.join(str(id) for id in taken_employee_ids)

Build a dictionary with single elements or lists as values

I have a list of dictionaries:
mydict = [
{'name': 'test1', 'value': '1_1'},
{'name': 'test2', 'value': '2_1'},
{'name': 'test1', 'value': '1_2'},
{'name': 'test1', 'value': '1_3'},
{'name': 'test3', 'value': '3_1'},
{'name': 'test4', 'value': '4_1'},
{'name': 'test4', 'value': '4_2'},
]
I would like to use it to create a dictionary where the values are lists or single values depending of number of their occurrences in the list above.
Expected output:
outputdict = {
'test1': ['1_1', '1_2', '1_3'],
'test2': '2_1',
'test3': '3_1',
'test4': ['4_1', '4_2'],
}
I tried to do it the way below but it always returns a list, even when there is just one value element.
outputdict = {}
outputdict.setdefault(mydict.get('name'), []).append(mydict.get('value'))
The current output is:
outputdict = {
'test1': ['1_1', '1_2', '1_3'],
'test2': ['2_1'],
'test3': ['3_1'],
'test4': ['4_1', '4_2'],
}
Do what you have already done, and then convert single-element lists afterwards:
outputdict = {
name: (value if len(value) > 1 else value[0])
for name, value in outputdict.items()
}
You can use a couple of the built-in functions mainly itertools.groupby:
from itertools import groupby
from operator import itemgetter
mydict = [
{'name': 'test1', 'value': '1_1'},
{'name': 'test2', 'value': '2_1'},
{'name': 'test1', 'value': '1_2'},
{'name': 'test1', 'value': '1_3'},
{'name': 'test3', 'value': '3_1'},
{'name': 'test4', 'value': '4_1'},
{'name': 'test4', 'value': '4_2'},
]
def keyFunc(x):
return x['name']
outputdict = {}
# groupby groups all the items that matches the returned value from keyFunc
# in our case it will use the names
for name, groups in groupby(mydict, keyFunc):
# groups will contains an iterator of all the items that have the matched name
values = list(map(itemgetter('value'), groups))
if len(values) == 1:
outputdict[name] = values[0]
else:
outputdict[name] = values
print(outputdict)

Fastest method: for value in DictA, find value in DictB and retrieve other DictB value?

For each item in dictA, I want to search for it in dictB, if dictB has it then I want to pull some other values from dictB and add it to dictA.
An example that is working is here, however it is rather slow as I have 50,000+ items to search through and it will perform this similar function on multiple dicts.
Is there a fast method of performing this search?
dictA = [
{'id': 12345},
{'id': 67890},
{'id': 11111},
{'id': 22222}
]
dictB = [
{'id': 63351, 'name': 'Bob'},
{'id': 12345, 'name': 'Carl'},
{'id': 59933, 'name': 'Amy'},
{'id': 11111, 'name': 'Chris'}
]
for i in dictA:
name = None
for j in dictB:
if i['id'] == j['id']:
name = j['name']
i['name'] = name
The dictA output after this would be:
dictA = [
{'id': 12345, 'name': 'Carl'},
{'id': 67890, 'name': None},
{'id': 11111, 'name': 'Chris'},
{'id': 22222, 'name': None}
]
The given is list of dict. You can create dict from that assuming id is uninque. Converting from list of dict to dict will work for your case.
dictA = [
{'id': 12345},
{'id': 67890},
{'id': 11111},
{'id': 22222}
]
dictB = [
{'id': 63351, 'name': 'Bob'},
{'id': 12345, 'name': 'Carl'},
{'id': 59933, 'name': 'Amy'},
{'id': 11111, 'name': 'Chris'}
]
actual_dictB = dict()
for d in dictB:
actual_dictB[d['id']] = d['name']
for i in dictA:
i['name'] = actual_dictB.pop(i['id'], None) # now search have became O(1) constant. So best time complexity achived O(n) n=length of dictA
print(dictA)
Follow up for additional question:
actual_dictB = dict()
for d in dictB:
id_ = d['id']
d.pop('id')
actual_dictB[id_] = d
tmp = dict([(k,None) for k in dictB[0].keys() if k!='id'])
for i in dictA:
if i['id'] not in actual_dictB:
i.update(tmp)
else:
i.update(actual_dictB[i['id']])
print(dictA)

Setup up a hierarchy from dicts

I have a single CSV file of employees where I have employee data including the name, boss, department id and department name.
By reading that CSV file, I have created those 2 dict structures:
dep = {}
dep[1] = {'name': 'Sales', 'parent': None}
dep[2] = {'name': 'National Sales', 'parent': None}
dep[3] = {'name': 'International Sales', 'parent': None}
dep[4] = {'name': 'IT', 'parent': None}
dep[5] = {'name': 'Development', 'parent': None}
dep[6] = {'name': 'Support', 'parent': None}
dep[7] = {'name': 'Helpdesk', 'parent': None}
dep[8] = {'name': 'Desktop support', 'parent': None}
dep[9] = {'name': 'CEO', 'parent': None}
emp = {}
emp[1] = {'name': 'John', 'boss': None, 'dep': 9}
emp[2] = {'name': 'Jane', 'boss': 1, 'dep': 1}
emp[3] = {'name': 'Bob', 'boss': 2, 'dep': 1}
emp[4] = {'name': 'Clara', 'boss': 2, 'dep': 2}
emp[5] = {'name': 'George', 'boss': 3, 'dep': 2}
emp[6] = {'name': 'Steve', 'boss': 2, 'dep': 3}
emp[7] = {'name': 'Joe', 'boss': 1, 'dep': 4}
emp[8] = {'name': 'Peter', 'boss': 7, 'dep': 5}
emp[9] = {'name': 'Silvia', 'boss': 7, 'dep': 6}
emp[10] = {'name': 'Mike', 'boss': 9, 'dep': 7}
emp[11] = {'name': 'Lukas', 'boss': 10, 'dep': 7}
emp[12] = {'name': 'Attila', 'boss': 7, 'dep': 8}
emp[13] = {'name': 'Eva', 'boss': 12, 'dep': 8}
Out of this I have 2 tasks:
Create a hierarchy of departments. (basically fill the value of the
parent key)
Display (list) all the departments and employees for a boss
Expected result for the point #2 would be (everybody working in sales):
employees = {1: (2, 3, 4, 5, 6)}
for everybody working in National Sales:
employees = {4: (5)}
and for everybody working in International Sales (Steve is the only one, nobody is working for him)):
employees = {6: None}
How to achieve this in a performant manner (I have to handle several thousands employees)?
EDIT:
This a (simplified) CSV file structure:
id;name;boss;dep_id;dep_name
1;John;;9;CEO
2;Jane;1;1;Sales
3;Bob;2;1;Sales
4;Clara;2;2;National Sales
5;George;3;2;National Sales
6;Steve;2;3;International Sales
7;Joe;1;4;IT
8;Peter;7;5;Development
9;Silvia;7;6;Support
10;Mike;9;7;Helpdesk
11;Lukas;10;7;Helpdesk
12;Attila;7;8;Desktop support
13;Eva;12;8;Desktop support
As suggested in the comments, here is a solution using pandas. The file is mocked using your example data, and it should be plenty fast for only a few thousand entries.
from StringIO import StringIO
import pandas as pd
f = StringIO("""
id;name;boss;dep_id;dep_name
1;John;1;9;CEO
2;Jane;1;1;Sales
3;Bob;2;1;Sales
4;Clara;2;2;National Sales
5;George;3;2;National Sales
6;Steve;2;3;International Sales
7;Joe;1;4;IT
8;Peter;7;5;Development
9;Silvia;7;6;Support
10;Mike;9;7;Helpdesk
11;Lukas;10;7;Helpdesk
12;Attila;7;8;Desktop support
13;Eva;12;8;Desktop support
""")
# load data
employees = pd.read_csv(f, sep=';', index_col=0)
### print a department ###
# Filter by department and print the names
print employees[employees.dep_id == 7].name
### build org hierarchy ###
# keep only one entry per department (assumes they share a boss)
org = employees[['boss', 'dep_id']].drop_duplicates('dep_id')
# follow the boss id to their department id
# note: the CEO is his own boss, to avoid special casing
org['parent'] = org.dep_id.loc[org['boss']].values
# reindex by department id, and keep only the parent column
# note: the index is like your dictionary key, access is optimized
org = org.set_index('dep_id')[['parent']]
print org

Categories