Flatten list of list into list for dictionary - python

I have a dictionary that looks like this:
{'data': [['748','','285','102','76024']]}
and I want to flatten the lists to look like this:
{'data': ['748','','285','102','76024']}
I have tried this from here:
[item for sublist in data.items() for item in sublist]
but it gives me:
['data',
[['748',
'',
'285',
'102',
'76024',
'88',
'3',
'89%831',
'77%',
'',
'68%632',
'19%177',
'13%120']]]

Based on the title, I noticed that you might have list of lists in each item in your dictionary. Using itertools.chain() you can merge multiple lists into one:
import itertools
data = {'data': [['748','','285','102','76024']]}
data1 = {'data': [['748','','285','102','76024'], ['12', '13', '14']]}
output = {k: list(itertools.chain(*v)) for k,v in data.items()}
output1 = {k: list(itertools.chain(*v)) for k,v in data1.items()}
Output:
# Output
{'data': ['748', '', '285', '102', '76024']}
# Output1
{'data': ['748', '', '285', '102', '76024', '12', '13', '14']}

Related

Delete item from a list of Dictionaries

I have a quick one.
I do have a long list of dictionaries that looks like this:
mydict = [{'id': '450118',
'redcap_event_name': 'preliminary_arm_1',
'redcap_repeat_instrument': '',
'redcap_repeat_instance': '',
'date_today': '2022-11-04',
'timestamp': '2022-11-04 10:49',
'doc_source': '1',
'hosp_id': '45',
'study_id': '18',
'participant_name': 'CHAR WA WAN',
'ipno': '141223',
'dob': '2020-06-30'},
{'id': '450118',
'redcap_event_name': 'preliminary_arm_1',
'redcap_repeat_instrument': '',
'redcap_repeat_instance': '',
'date_today': '2022-11-04',
'timestamp': '2022-11-04 10:49',
'doc_source': '1',
'hosp_id': '45',
'study_id': '01118',
'participant_name': 'CHARIT',
'ipno': '1413',
'dob': '2020-06-30'}]
Now I want to do a simple thing, I do want to delete this 3 items from the dictionaries ,'redcap_event_name','redcap_repeat_instrument','redcap_repeat_instance'.
I have tried writing this code but its not deleting at all
for k in mydict:
for j in k.keys():
if j == 'preliminary_arm_1':
del j
My final result is the original list of dictionaries but without the 3 items mentioned above. any help will highly be appreciated
You can iterate over each dict and then iterate over each key you want to delete. At the end delete key from each dict.
del_keys = ['redcap_event_name','redcap_repeat_instrument','redcap_repeat_instance']
for dct in mydict:
for k in del_keys:
# To delete a key regardless of whether it is in the dictionary or not
dct.pop(k, None)
print(mydict)
Output:
[{'id': '450118',
'date_today': '2022-11-04',
'timestamp': '2022-11-04 10:49',
'doc_source': '1',
'hosp_id': '45',
'study_id': '18',
'participant_name': 'CHAR WA WAN',
'ipno': '141223',
'dob': '2020-06-30'},
{'id': '450118',
'date_today': '2022-11-04',
'timestamp': '2022-11-04 10:49',
'doc_source': '1',
'hosp_id': '45',
'study_id': '01118',
'participant_name': 'CHARIT',
'ipno': '1413',
'dob': '2020-06-30'}]
Maybe it helps:
[{j: k[j] for j in k.keys() if j not in ['redcap_event_name','redcap_repeat_instrument','redcap_repeat_instance']}
for k in mydict]

create a specific python dictionary from 2 lists

I have the following data:
fsm_header = ['VLAN_ID', 'NAME', 'STATUS']
fsm_results = [['1', 'default', 'active'],
['2', 'VLAN0002', 'active'],
['3', 'VLAN0003', 'active']]
I want to create a specific dictionary like this:
{'VLAN_ID':['1','2','3'],
'NAME':['default','VLAN0002','VLAN0003'],
'STATUS':['active','active','active']}
I'm having trouble finding the right combination, as the one I'm using:
dict(zip(fsm_header, row)) for row in fsm_results
gives me another type of useful output, but not the one I mentioned above.
I would prefer to see something without using the zip function, but even with zip is ok.
You need to unpack and zip fsm_results too:
out = {k:list(v) for k,v in zip(fsm_header, zip(*fsm_results))}
Output:
{'VLAN_ID': ['1', '2', '3'],
'NAME': ['default', 'VLAN0002', 'VLAN0003'],
'STATUS': ['active', 'active', 'active']}
If you don't mind tuple as values; then you could use:
out = dict(zip(fsm_header, zip(*fsm_results)))
Output:
{'VLAN_ID': ('1', '2', '3'),
'NAME': ('default', 'VLAN0002', 'VLAN0003'),
'STATUS': ('active', 'active', 'active')}
You could also write the same thing using dict.setdefault:
out = {}
for lst in fsm_results:
for k, v in zip(fsm_header, lst):
out.setdefault(k, []).append(v)

How to convert list of dictionaries to list of tuples?

I have a list of dictionaries in python like:
lst = [{'f_id': '1', 'm_id':'22', 'fm_id':'23'},{'f_id': '2', 'm_id':'32', 'fm_id':33}]
I'm trying to update the values in dictionary like
lst = [{'f_id': '3', 'm_id':'22', 'fm_id':'N'},{'f_id': '4', 'm_id':'32', 'fm_id':N}]
and get only values from dictionary and put them in list of tuples like:
new_lst = [('3', '22', 'N'),('4', '32', 'N')]
I've tried:
list_of_dict = []
for each in lst:
for key, values in each.items():
temp = values
list_of_dict.append(temp)
print(list_of_dict)
but I'm getting a different output. I'm tried different approaches but not getting the expected output.
Have you tried this?
lst = [{'f_id': '1', 'm_id':'22', 'fm_id':'23'},{'f_id': '2', 'm_id':'32', 'fm_id': '33'}]
new_lst = [tuple(d.values()) for d in lst]
Here is a one liner solution:
j=[tuple([str(x) for x in d.values()]) for d in lst ]
Output:
[('1', '22', '23'), ('2', '32', '33')]

Python - Issue when merging lists with repeating values into a dictionary

When my first lists has repeating values, it causes the merge to fail for some reason.
names = ['bob', 'bob', 'bob', 'bob']
id = ['15', '12', '19', '20']
rating = ['100', '90', '100', '80']
dictionary = dict(zip(names, zip(id, rating)))
print(dictionary)
will output
{'bob': ('20', '80')}
However, if I simply change all the names to be unique, it will output as expected.
names = ['bob', 'sally', 'john', 'jill']
id = ['15', '12', '19', '20']
rating = ['100', '90', '100', '80']
dictionary = dict(zip(names, zip(id, rating)))
print(dictionary)
same code with unique names now outputs
{'bob': ('15', '100'), 'john': ('19', '100'), 'sally': ('12', '90'), 'jill': ('20', '80')}
What can I do better than "dict(zip(names, zip(id, rating)))" so I can repeat 'bob' as much as I want?
Well, unfortunately, you can't use the same key for different values in a dictionary; that would mean that each key would have a different value, which would break the main idea. What I would do instead, if you must have repeating keys, is to change the name according to its position in the original list.
names = ['bob', 'bob', 'bob', 'bob']
id = ['15', '12', '19', '20']
rating = ['100', '90', '100', '80']
new_dict = {}
for i in range(len(names)):
new_dict[f'{names[i]} #{i}'] = (id[i], rating[i])
You will get a dict consisting of the names in names and their relative positions. This will result in a ListIndex error if you have id or rating shorter than names.
you can try this:
a={}
b=[]
for n,i,r in zip(names,id,rating):
a[n] = (i,r)
b.append(a)
This will return you a list of dictionary
output:
[{'bob': ('20', '80')},
{'bob': ('20', '80')},
{'bob': ('20', '80')},
{'bob': ('20', '80')}]

How to sort data in the dictionary of list of dictionary in python?

Please help me. I have dataset like this:
my_dict = { 'project_1' : [{'commit_number':'14','name':'john'},
{'commit_number':'10','name':'steve'}],
'project_2' : [{'commit_number':'12','name':'jack'},
{'commit_number':'15','name':'anna'},
{'commit_number':'11','name':'andy'}]
}
I need to sort the dataset based on the commit number in descending order and make it into a new list by ignoring the name of the project using python. The list expected will be like this:
ordered_list_of_dict = [{'commit_number':'15','name':'anna'},
{'commit_number':'14','name':'john'},
{'commit_number':'12','name':'jack'},
{'commit_number':'11','name':'andy'},
{'commit_number':'10','name':'steve'}]
Thank you so much for helping me.
Extract my_dict's values as a list of lists*
Join each sub-list together (flatten dict_values) to form a flat list
Sort each element by commit_number
*list of lists on python2. On python3, a dict_values object is returned.
from itertools import chain
res = sorted(chain.from_iterable(my_dict.values()),
key=lambda x: x['commit_number'],
reverse=True)
[{'commit_number': '15', 'name': 'anna'},
{'commit_number': '14', 'name': 'john'},
{'commit_number': '12', 'name': 'jack'},
{'commit_number': '11', 'name': 'andy'},
{'commit_number': '10', 'name': 'steve'}]
On python2, you'd use dict.itervalues instead of dict.values to the same effect.
Coldspeed's answer is great as usual but as an alternative, you can use the following:
ordered_list_of_dict = sorted([x for y in my_dict.values() for x in y], key=lambda x: x['commit_number'], reverse=True)
which, when printed, gives:
print(ordered_list_of_dict)
# [{'commit_number': '15', 'name': 'anna'}, {'commit_number': '14', 'name': 'john'}, {'commit_number': '12', 'name': 'jack'}, {'commit_number': '11', 'name': 'andy'}, {'commit_number': '10', 'name': 'steve'}]
Note that in the list-comprehension you have the standard construct for flattening a list of lists:
[x for sublist in big_list for x in sublist]
I'll provide the less-pythonic and more reader-friendly answer.
First, iterate through key-value pairs in my_dict, and add each element of value to an empty list. This way you avoid having to flatten out a list of lists:
commits = []
for key, val in my_dict.items():
for commit in val:
commits.append(commit)
which gives this:
In [121]: commits
Out[121]:
[{'commit_number': '12', 'name': 'jack'},
{'commit_number': '15', 'name': 'anna'},
{'commit_number': '11', 'name': 'andy'},
{'commit_number': '14', 'name': 'john'},
{'commit_number': '10', 'name': 'steve'}]
Then sort it in descending order:
sorted(commits, reverse = True)
This will sort based on 'commit_number' even if you don't specify it because it comes alphabetically before 'name'. If you want to specify it for the sake of defensive coding, this would be fastest and cleanest way, to the best of my knowledge :
from operator import itemgetter
sorted(commits, key = itemgetter('commit_number'), reverse = True)

Categories