List of values to dictionary - python

I'm trying to make a list of values to a list of dictionary's based on my set keys. I tried the following but i'm loosing all the other values because of the duplicate key names.
>>> values = ['XS ', '1', 'S ', '10', 'M ', '1', 'L ', '10', 'XL ', '10']
>>> keys = ['size', 'stock'] * (len(values) / 2)
>>> result = dict(zip(keys, values))
>>> print result
{'stock': '10', 'size': 'XL '}
What i'm trying to achieve is a list of the dicts like below. How can I achieve this?
[{'stock': '10', 'size': 'XL '}, {'stock': '10', 'size': 'L'}, ......]

You can use a list comprehension like following:
>>> values = ['XS ', '1', 'S ', '10', 'M ', '1', 'L ', '10', 'XL ', '10']
>>> [{'size':i, 'stock':j} for i, j in zip(values[0::2], values[1::2])]
[{'stock': '1', 'size': 'XS '}, {'stock': '10', 'size': 'S '}, {'stock': '1', 'size': 'M '}, {'stock': '10', 'size': 'L '}, {'stock': '10', 'size': 'XL '}]
Note that in this case you don't have to multiply the keys.

Usually the point of using a dict is to associate unique keys to associated values, you were originally trying to associate size: ... and stock: ... for each item but why not link the size to stock? In that case you would simply do:
result = dict(zip(values[::2], values[1::2]))
or without needing slicing:
value_iter = iter(values)
result = dict(zip(value_iter, value_iter))
This grabs two elements from the list at a time.
This way you still know that a given key in the dict is the size and the associated value is the stock for that size.

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]

Return only index zero in a list comprehension

To create a list with the values that I retrieve from a spreadsheet, I do it like this:
result = {'range': 'Winning_Margin!G2:O1000', 'majorDimension': 'ROWS',
'values': [['10148734', 'CD Olimpia', 'CD Vida', '1',
'71', '85', '14.00', '1.40', '2-0'],
['', '', '', '', '', '', '', '', ''],
['10024627', 'Sporting Kansas City', 'FC Dallas',
'2', '35', '1', '-34.00', '2.88']]}
for a in result["values"]:
a.extend([''] * (max(map(len, result["values"])) - len(a)))
spreadsheets_match_id = [item for sublist in result["values"] for item in (sublist or ['']) if sublist[-1] != '']
This way returns the entire index:
['10148734', 'CD Olimpia', 'CD Vida', '1', '71', '85', '14.00', '1.40', '2-0']
But my need is just the first index of each list of list, in this case the result is:
['10148734']
Tried to make each item become item[0] but when trying to do that, it either says that item doesn't exist or returns the first letter of each of the list's indexes within the list like ['1', 'C', 'C', '1', '7', '8', '1', '1', '2'].
Edit:
You can check if the last element of the sublist is '' or not and keep the first elements of the ones that aren't:
out = [sublist[0] for sublist in result["values"] if sublist[-1] !='']
Old answer:
IIUC, you want to get the first element of a sublist that is not '', right? Then you can create a single element list in a list comprehension and iterate over it in a nested loop to check if it is '' or not:
out = [item for sublist in result["values"] for item in [sublist[0]] if item !='']
Output:
['10148734', '10024627']

How to convert list of strings to list of dictionaries in python

Suppose I have a list of strings in Python:
['Name: volume_test_add_volume_to_cg_2019_03_07-12_21_37', 'Index: 24',
'Name: volume_xx111', 'Index: 3', 'Name: volume_xx11541', 'Index: 4',
'Name: Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10', 'Index: 6']
How to convert them to a list of dictionaries so the final result will be like this:
[
{'Name': 'volume_test_add_volume_to_cg_2019_03_07-12_21_37', 'Index': '24'},
{'Name': 'volume_xx111', 'Index': '3'},
{'Name': 'volume_xx11541', 'Index': '4'},
{'Name': 'Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10', 'Index': '6}
]
You need to decide, in code, how to group the strings into dictionaries. Perhaps there are always 2 elements each, or there is always a Name entry, or you simply need to create a new dictionary each time a key has been seen before.
If there are always N elements per dictionary, then iterate in chunks of that size:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
results = [
dict(tuple(map(str.strip, entry.split(': '))) for entry in per_dict)
for per_dict in chunks(inputlist, 2)
]
Demo:
>>> from pprint import pprint
>>> inputlist = ['Name: volume_test_add_volume_to_cg_2019_03_07-12_21_37', 'Index: 24', 'Name: volume_xx111', 'Index: 3', 'Name: volume_xx11541', 'Index: 4', 'Name: Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10', 'Index: 6']
>>> def chunks(l, n):
... """Yield successive n-sized chunks from l."""
... for i in range(0, len(l), n):
... yield l[i:i + n]
...
>>> [
... dict(tuple(map(str.strip, entry.split(': '))) for entry in per_dict)
... for per_dict in chunks(inputlist, 2)
... ]
[{'Name': 'volume_test_add_volume_to_cg_2019_03_07-12_21_37', 'Index': '24'}, {'Name': 'volume_xx111', 'Index': '3'}, {'Name': 'volume_xx11541', 'Index': '4'}, {'Name': 'Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10', 'Index': '6'}]
>>> pprint(_)
[{'Index': '24', 'Name': 'volume_test_add_volume_to_cg_2019_03_07-12_21_37'},
{'Index': '3', 'Name': 'volume_xx111'},
{'Index': '4', 'Name': 'volume_xx11541'},
{'Index': '6',
'Name': 'Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10'}]
If seeing a key repeat is the better approach, then start with a list result containing an empty dictionary; you add key-value pairs to result[-1]. Then process your strings one by one, splitting each on the ':' character to create a key and value pair. If the key already is found in the most recent dictionary, start a new empty one:
results = [{}]
for entry in inputlist:
key, value = map(str.strip, entry.split(':')) # removing surrounding whitespace
if key in results[-1]:
# start a new dictionary
results.append({})
results[-1][key] = value
By checking for the key existing, it no longer matters if a Name and Index entry got swapped.
Demo:
>>> results = [{}]
>>> for entry in inputlist:
... key, value = map(str.strip, entry.split(':')) # removing surrounding whitespace
... if key in results[-1]:
... # start a new dictionary
... results.append({})
... results[-1][key] = value
...
>>> pprint(results)
[{'Index': '24', 'Name': 'volume_test_add_volume_to_cg_2019_03_07-12_21_37'},
{'Index': '3', 'Name': 'volume_xx111'},
{'Index': '4', 'Name': 'volume_xx11541'},
{'Index': '6',
'Name': 'Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10'}]
My solution is the following:
lista = ['Name: volume_test_add_volume_to_cg_2019_03_07-12_21_37', 'Index: 24',
'Name: volume_xx111', 'Index: 3',
'Name: volume_xx11541', 'Index: 4',
'Name: Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10', 'Index: 6']
result = []
for n, item in enumerate(lista):
if n % 2 == 0:
result.append({'Name': item[item.find(':') + 2:],
'Index': lista[n + 1][lista[n + 1].find(':') + 2:]})
print(result)
With this output:
[{'Name': 'volume_test_add_volume_to_cg_2019_03_07-12_21_37', 'Index': '24'}, {'Name': 'volume_xx111', 'Index': '3'}, {'Name': 'volume_xx11541', 'Index': '4'}, {'Name': 'Volume_test_add_volume_mandatory_params_2019_03_06-16_50_10', 'Index': '6'}]

Nested dictionary issue

I need to create a program that takes a CSV file and returns a nested dictionary. The keys for the outer dictionary should be the first value in each row, starting from the second one (so as to omit the row with the column names). The value for each key in the outer dictionary should be another dictionary, which I explain below.
The inner dictionary's keys should be the column names, while the values should be the value corresponding to that column in each row.
Example:
For a CSV file like this:
column1, column2, column3, column4
4,12,5,11
29,47,23,41
66,1,98,78
I would like to print out the data in this form:
my_dict = {
'4': {'column1':'4','column2':'12', 'column3':'5', 'column4':'11'},
'29': {'column1':'29', 'column2':'47', 'column3':'23', 'column4':'41'},
'66': {'column1':'66', 'column2':'1', 'column3':'98', 'column4':'78'}
}
The closest I've gotten so far (which isn't even close):
import csv
import collections
def csv_to_dict(file, delimiter, quotechar):
list_inside_dict = collections.defaultdict(list)
with open(file, newline = '') as csvfile:
reader = csv.DictReader(csvfile, delimiter=delimiter, quotechar=quotechar)
for row in reader:
for (k,v) in row.items():
list_inside_dict[k].append(v)
return dict(list_inside_dict)
If I try to run the function with the example CSV file above, delimiter = ",", and quotechar = "'", it returns the following:
{'column1': ['4', '29', '66'], ' column2': ['12', '47', '1'], ' column3': ['5', '23', '98'], ' column4': ['11', '41', '78']}
At this point I got lost. I tried to change:
list_inside_dict = collections.defaultdict(list)
for
list_inside_dict = collections.defaultdict(dict)
And then simply changing the value for each key, since I cannot append into a dictionary, but it all got really messy. So I started from scratch and found I reached the same place.
You can use a dictionary comprehension:
import csv
with open('filename.csv') as f:
header, *data = csv.reader(f)
final_dict = {a:dict(zip(header, [a, *b])) for a, *b in data}
Output:
{'4': {'column1': '4', ' column2': '12', ' column3': '5', ' column4': '11'},
'29': {'column1': '29', ' column2': '47', ' column3': '23', ' column4': '41'},
'66': {'column1': '66', ' column2': '1', ' column3': '98', ' column4': '78'}}
You can use pandas for that task.
>>> df = pd.read_csv('/path/to/file.csv')
>>> df.index = df.iloc[:, 0]
>>> df.to_dict('index')
Not sure why you want to duplicate the value of the first column, but in case you don't the above simplifies to:
>>> pd.read_csv('/path/to/file.csv', index_col=0).to_dict('index')
This is similar to this answer, however, I believe it could be better explained.
import csv
with open('filename.csv') as f:
headers, *data = csv.reader(f)
output = {}
for firstInRow, *restOfRow in data:
output[firstInRow] = dict(zip(headers, [firstInRow, *restOfRow]))
print(output)
What this does is loops through the rows of data in the file with the first value as the index and the following values in a list. The value of the index in the output dictionary is then set by zipping the list of headers and the list of values. That output[first] = ... line is the same as writing output[firstInRow] = {header[1]: firstInRow, header[2]: restOfRow[1], ...}.
Output:
{'4': {'column1': '4', ' column2': '12', ' column3': '5', ' column4': '11'},
'29': {'column1': '29', ' column2': '47', ' column3': '23', ' column4': '41'},
'66': {'column1': '66', ' column2': '1', ' column3': '98', ' column4': '78'}}
It is a couple of zips to get what you want.
Instead of a file, we can use a string for the csv. Just replace that part with a file.
Given:
s='''\
column1, column2, column3, column4
4,12,5,11
29,47,23,41
66,1,98,78'''
You can do:
import csv
data=[]
for row in csv.reader(s.splitlines()): # replace 'splitlines' with your file
data.append(row)
header=data.pop(0)
col1=[e[0] for e in data]
di={}
for c,row in zip(col1,data):
di[c]=dict(zip(header, row))
Then:
>>> di
{'4': {'column1': '4', ' column2': '12', ' column3': '5', ' column4': '11'},
'29': {'column1': '29', ' column2': '47', ' column3': '23', ' column4': '41'},
'66': {'column1': '66', ' column2': '1', ' column3': '98', ' column4': '78'}}
On Python 3.6+, the dicts will maintain insertion order. Earlier Python's will not.

Remove quotes from list of dictionaries in python

How can I remove the single quotes from the following so it can be recognized as a list of one dictionary object as apposed to a list of one string object? Given that it is a list, I cannot use pd.replace.
['{"PLAYER":"Player Name","SALARY":"0000.00","OPP":"CI","POS":"BR","TEAM":"IT","SCHEDULE_ID":"40623","PLAYERID":"12322","GP":"5","TAR":"64","RZTAR":"6","POW TAR":"32.99%","WEEK 2":"11","WEEK 3":"14","WEEK 4":"9","WEEK 5":"19","ARDS":"545","YPT":"8.52","REC":"40","REC RATE":"62.50%"}']
You can use ast.literal_eval:
import ast
s = ['{"PLAYER":"Player Name","SALARY":"0000.00","OPP":"CI","POS":"BR","TEAM":"IT","SCHEDULE_ID":"40623","PLAYERID":"12322","GP":"5","TAR":"64","RZTAR":"6","POW TAR":"32.99%","WEEK 2":"11","WEEK 3":"14","WEEK 4":"9","WEEK 5":"19","ARDS":"545","YPT":"8.52","REC":"40","REC RATE":"62.50%"}']
final_s = [ast.literal_eval(i) for i in s]
Output:
[{'SALARY': '0000.00', 'REC RATE': '62.50%', 'OPP': 'CI', 'YPT': '8.52', 'TAR': '64', 'GP': '5', 'PLAYERID': '12322', 'WEEK 3': '14', 'POS': 'BR', 'ARDS': '545', 'WEEK 2': '11', 'PLAYER': 'Player Name', 'SCHEDULE_ID': '40623', 'POW TAR': '32.99%', 'WEEK 4': '9', 'TEAM': 'IT', 'RZTAR': '6', 'REC': '40', 'WEEK 5': '19'}]
just use eval() for the purpose
s=['{"PLAYER":"PlayerName","SALARY":"0000.00","OPP":"CI","POS":"BR","TEAM":"IT","SCHEDULE_ID":"40623","PLAYERID":"12322","GP":"5","TAR":"64","RZTAR":"6","POW TAR":"32.99%","WEEK 2":"11","WEEK 3":"14","WEEK 4":"9","WEEK 5":"19","ARDS":"545","YPT":"8.52","REC":"40","REC RATE":"62.50%"}']
s = [eval(item) for item in s]

Categories