Need help in appending dictionary items in python - python

I am trying to get movies by genres from tmdb movie dataset by converting it into json.
There should be multiple entries for a specific genre like 'adventure', but all i get to see is the last record and seems like the previous records are getting overwritten. I have verified this by adding a print statement in the if statement and the details are showing up in the console but somehow getting overwritten.
Any help would be appreciated. Thanks!!
final_list = []
for i in range(1,1000):
if genre_name in data[str(i)]['genres']:
movie_dict["Title"] = data[str(i)]['title']
movie_dict["Language"] = data[str(i)]['original_language']
final_list = [movie_dict]
return final_list

There are two obvious problems. You redefine final_list in the loop and you return during the first loop.
Fixing that will give you something like this:
def myfunction(data, genre_name):
movie_dict = {}
final_list = []
for i in range(1,1000):
if genre_name in data[str(i)]['genres']:
movie_dict["Title"] = data[str(i)]['title']
movie_dict["Language"] = data[str(i)]['original_language']
final_list.append(movie_dict)
return final_list
Now there is another, more subtle problem. You always add the same dictionary to the list.
To give an example:
d = {}
l = []
for i in range(5):
d['x'] = i ** 2
l.append(d)
print(l)
Now l contains the same dictionary 5 times and this dictionary will have the content from the last iteration of the loop: [{'x': 16}, {'x': 16}, {'x': 16}, {'x': 16}, {'x': 16}]. To fix this you have to create the dictionary in the loop, so in your code you have to move movie_dict = {} to an appropriate place:
def myfunction(data, genre_name):
final_list = []
for i in range(1,1000):
if genre_name in data[str(i)]['genres']:
movie_dict = {}
movie_dict["Title"] = data[str(i)]['title']
movie_dict["Language"] = data[str(i)]['original_language']
final_list.append(movie_dict)
return final_list
Now some more advanced stuff. I assume data is a dictionary since you use a string for indexing. If you're not limited to 1000 entries but want to access all the values in the dictionary you can loop over the dictionaries values:
def myfunction(data, genre_name):
final_list = []
for entry in data.values():
if genre_name in entry['genres']:
movie_dict = {}
movie_dict["Title"] = entry['title']
movie_dict["Language"] = entry['original_language']
final_list.append(movie_dict)
return final_list
Now let us create the dictionary on the fly in the call to append.
def myfunction(data, genre_name):
final_list = []
for entry in data.values():
if genre_name in entry['genres']:
final_list.append({'Title': entry['title'], 'Language': entry['original_language']})
return final_list
This can be rewritten as a list comprehension:
def myfunction(data, genre_name):
return [{'Title': entry['title'], 'Language': entry['original_language']} for entry in data.values() if genre_name in entry['genres']]
That's all.

Try using final_list.append(movie_dict).

Bro you were actually actually returning the list after each value was added try this way and it will not overwrite it. The main reason is that you were returning the list in the for loop and everytime the loop run it save new dictionary in the list and remove the old one
final_list = []
for i in range(1,1000):
if genre_name in data[str(i)]['genres']:
movie_dict["Title"] = data[str(i)]['title']
movie_dict["Language"] = data[str(i)]['original_language']
final_list.append(movie_dict)
return final_list

Related

Reformating a dictionary of list based on items in another list

I have a dictionary of lists like
source = {"name":["hans","james","mat"],"country":["spain"],"language":["english","french"]}
and another list like
data_not_avail = ["hans","spain","mat"]
How is it possible to reformat source dictionary into the following format
{
"exist":{"name":["james"], "language":["english","french"]},
"not_exist":{"name":["hans","mat"], "country":["spain"]}
}
I was trying to solve by finding the key of item which are present in list but it was not a success
data_result = {}
keys_list = []
for v in data_not_avail:
keys = [key for key, value in source.items() if v in value]
data_result.update({keys[0]:[v]})
keys_list.extend(keys)
This is a approach, you can use a list comprehension (or python built in filter) to filter every element within source lists with the content of data_not_avail.
data = {"exist": {}, "not_exist": {}}
for key, value in source.items():
data["exist"][key] = [v for v in value if v not in data_not_avail]
data["not_exist"][key] = [v for v in value if v in data_not_avail]
# if you dont need empty list in the result
if not data["exist"][key]:
del data["exist"][key]
if not data["not_exist"][key]:
del data["not_exist"][key]
Naive way of solving it is this, check it out.
values = list(source.values())
exist_values = []
not_values = []
for l in values:
temp_exist = []
temp_not = []
for item in l:
if item not in data_not_avail:
temp_exist.append(item)
else:
temp_not.append(item)
exist_values.append(temp_exist)
not_values.append(temp_not)
exist = {}
not_exist = {}
keys = ['name', 'language', 'country']
for i,key in enumerate(keys):
if len(exist_values[i]) != 0:
exist[key] = exist_values[i]
if len(not_values[i]) != 0:
not_exist[key] = not_values[i]
print(exist, not_exist)
#{'name': ['james'], 'country': ['english', 'french']}
#{'name': ['hans', 'mat'], 'language': ['spain']}

How could I create a dictionary taking specific strings of elements of a list?

I have a list with elements that contain values separated by "_" and I need to take the 4th as the values and the 5 and 6th as keys of a dictionary
My list:
['MLID_D_08_NGS_34_H08.fsa',
'MLID_D_17_W2205770_Michael_Jordan_A10.fsa',
'MLID_D_18_W2205770_Michael_Jordan_B10.fsa',
'MLID_D_19_W2205768_Maradona_Guti_C10.fsa',
'MLID_D_20_W2205768_Maradona_Guti_D10.fsa',
'MLID_D_38_No_DNA_F12.fsa']
I am trying to get a dictionary like this
thisdict = {
"34_H08": "NGS",
"Michael_Jordan_A10": "W2205770",
"Michael_Jordan_B10": "W2205770",
...
"DNA_F12": "No",
}
Optimised way of creating same dictionary
thisdict = dict(
(lambda x: ('_'.join(x[4:6]), x[3]))(s.split('_'))
for s in lst
)
Using reduce function
reduce(lambda x, y: x.update({ '_'.join(y.split('_')[4:6]): y.split('_')[3] }) or x, lst, {})
Try this:
lst = ['MLID_D_08_NGS_34_H08.fsa',
'MLID_D_17_W2205770_Michael_Jordan_A10.fsa',
'MLID_D_18_W2205770_Michael_Jordan_B10.fsa',
'MLID_D_19_W2205768_Maradona_Guti_C10.fsa',
'MLID_D_20_W2205768_Maradona_Guti_D10.fsa',
'MLID_D_38_No_DNA_F12.fsa']
dic = {}
for name in lst:
name = name.split(".")[0].split("_")
dic["_".join(name[4:])] = name[3]
print(dic)
This code may help you.
lst = ['MLID_D_08_NGS_34_H08.fsa',
'MLID_D_17_W2205770_Michael_Jordan_A10.fsa',
'MLID_D_18_W2205770_Michael_Jordan_B10.fsa',
'MLID_D_19_W2205768_Maradona_Guti_C10.fsa',
'MLID_D_20_W2205768_Maradona_Guti_D10.fsa',
'MLID_D_38_No_DNA_F12.fsa']
lst = [a.split('.') for a in lst] # split by .
dict_ = {}
for l in lst:
k = '_'.join(l[0].split('_')[4:]) # make key
v = l[0].split('_')[3] # make value
dict_[k]=v # add value to dict
print(dict_)
OUTPUT
{'34_H08': 'NGS',
'Michael_Jordan_A10': 'W2205770',
'Michael_Jordan_B10': 'W2205770',
'Maradona_Guti_C10': 'W2205768',
'Maradona_Guti_D10': 'W2205768',
'DNA_F12': 'No'}
As #matszwecja indicated s.split('_') is the way to go.
You can access different parts of the split as follows:
lst = ['MLID_D_08_NGS_34_H08.fsa',
'MLID_D_17_W2205770_Michael_Jordan_A10.fsa',
'MLID_D_18_W2205770_Michael_Jordan_B10.fsa',
'MLID_D_19_W2205768_Maradona_Guti_C10.fsa',
'MLID_D_20_W2205768_Maradona_Guti_D10.fsa',
'MLID_D_38_No_DNA_F12.fsa']
thisdict = {s.split('_')[4] + '_' + s.split('_')[5].split('.')[0]: s.split('_')[3] for s in lst}

How to create a list of dictionaries in python?

I am trying to make a list of dictionaries in python. Why don't these three methods produce the same results?
A = [{}]*2
A[0]['first_name'] = 'Tom'
A[1]['first_name'] = 'Nancy'
print A
B = [{},{}]
B[0]['first_name'] = 'Tom'
B[1]['first_name'] = 'Nancy'
print B
C = [None]*2
C[0] = {}
C[1] = {}
C[0]['first_name'] = 'Tom'
C[1]['first_name'] = 'Nancy'
print C
this is what I get:
[{'first_name': 'Nancy'}, {'first_name': 'Nancy'}]
[{'first_name': 'Tom'}, {'first_name': 'Nancy'}]
[{'first_name': 'Tom'}, {'first_name': 'Nancy'}]
Your first method is only creating one dictionary. It's equivalent to:
templist = [{}]
A = templist + templist
This extends the list, but doesn't make a copy of the dictionary that's in it. It's also equivalent to:
tempdict = {}
A = []
A.append(tempdict)
A.append(tempdict)
All the list elements are references to the same tempdict object.
Barmar has a very good answer why. I say you how to do it well :)
If you want to generate a list of empty dicts use a generator like this:
A = [{}for n in range(2)]
A[0]['first_name'] = 'Tom'
A[1]['first_name'] = 'Nancy'
print (A)

Using a for-loop to convert list to 2d dictionary

I am having trouble converting a 2d list into a 2d dictionary. I haven't worked much with 2d dictionaries prior to this so please bear with me. I am just wondering why this keeps pulling up a KeyError. In this quick example I would want the dictionary to look like {gender: { name: [food, color, number] }}
2dList = [['male','josh','chicken','purple','10'],
['female','Jenny','steak','blue','11']]
dict = {}
for i in range(len(2dList)):
dict[2dList[i][0]][2dList[i][1]] = [2dList[i][2], 2dList[i][3], 2dList[i][4]]
I keep getting the error message: KeyError: 'male'. I know this is how you add keys for a 1d dictionary, but am unsure regarding 2d dictionaries. I always believed it was:
dictionary_name[key1][key2] = value
You can try this :) It will also work if you have more than one male or female in your List
List = [['male','josh','chicken','purple','10'],
['female','Jenny','steak','blue','11']]
d = {}
for l in List:
gender = l[0]
name = l[1]
food = l[2]
color = l[3]
number = l[4]
if gender in d: # if it exists just add new name by creating new key for name
d[gender][name] = [food,color,number]
else: # create new key for gender (male/female)
d[gender] = {name:[food,color,number]}
You are attempting to build a nested dictionary. But are not explicitly initializing the second-layer dictionaries. You need to do this each time, a new key is encountered. Btw, 2dlist is an erroneous way to declare variables in python. This should work for you:
dList = [['male','josh','chicken','purple','10'],
['female','Jenny','steak','blue','11']]
dict = {}
for i in range(len(dList)):
if not dList[i][0] in dict.keys():
dict[dList[i][0]] = {}
dict[dList[i][0]][dList[i][1]] = [dList[i][2], dList[i][3], dList[i][4]]
print(dict)
To get more or less "sane" result use the following (list of dictionaries, each dict is in format {gender: { name: [food, color, number] }}):
l = [['male','josh','chicken','purple','10'], ['female','Jenny','steak','blue','11']]
result = [{i[0]: {i[1]:i[2:]}} for i in l]
print(result)
The output:
[{'male': {'josh': ['chicken', 'purple', '10']}}, {'female': {'Jenny': ['steak', 'blue', '11']}}]
You are getting a KeyError because you are trying to access a non-existing entry on the dictionary with male as the key
You can use defaultdict instead of dict.
from collections import defaultdict
2dList = [['male','josh','chicken','purple','10'],
['female','Jenny','steak','blue','11']]
dict = defaultdict(list)
for i in range(len(2dList)):
dict[2dList[i][0]][2dList[i][1]] = [2dList[i][2], 2dList[i][3], 2dList[i][4]]
Try this
twodList = [['male','josh','chicken','purple','10'],
['female','Jenny','steak','blue','11']]
dic = {twodList[i][0]: {twodList[i][1]: twodList[i][2:]} for i in range(len(twodList))}
As someone mentioned in the comments, you cannot have a variable starting with a number.
list1=[['male','josh','chicken','purple','10'],['female','Jenny','steak','blue','11'],['male','johnson','chicken','purple','10'],['female','jenniffer','steak','blue','11']]
dict = {}
for i in range(len(list1)):
if list1[i][0] in dict:
if list1[i][1] in dict[list1[i][0]]:
dict[list1[i][0]][list1[i][1]] = [list1[i][2], list1[i][3], list1[i][4]]
else:
dict[list1[i][0]][list1[i][1]] = {}
dict[list1[i][0]][list1[i][1]] = [list1[i][2], list1[i][3], list1[i][4]]
else:
dict[list1[i][0]] = {}
if list1[i][1] in dict[list1[i][0]]:
dict[list1[i][0]][list1[i][1]] = [list1[i][2], list1[i][3], list1[i][4]]
else:
dict[list1[i][0]][list1[i][1]] = {}
dict[list1[i][0]][list1[i][1]] = [list1[i][2], list1[i][3], list1[i][4]]
print dict
Above one gives below output:
{"male":{"josh":["chicken","purple","10"],"johnson":["chicken","purple","10"]},"female":{"jenniffer":["steak","blue","11"],"Jenny":["steak","blue","11"]}}

Nested lists to nested dicts

I've a list with master keys and a list of list of lists, where the first value of each enclosed list (like 'key_01') shall be a sub key for the corresponding values (like 'val_01', 'val_02'). The data is shown here:
master_keys = ["Master_01", "Master_02", "Master_03"]
data_long = [[['key_01','val_01','val_02'],['key_02','val_03','val_04'], ['key_03','val_05','val_06']],
[['key_04','val_07','val_08'], ['key_05','val_09','val_10'], ['key_06','val_11','val_12']],
[['key_07','val_13','val_14'], ['key_08','val_15','val_16'], ['key_09','val_17','val_18']]]
I would like these lists to be combined into a dictionary of dictionaries, like this:
master_dic = {
"Master_01": {'key_01':['val_01','val_02'],'key_02': ['val_03','val_04'], 'key_03': ['val_05','val_06']},
"Master_02": {'key_04': ['val_07','val_08'], 'key_05': ['val_09','val_10'], 'key_06': ['val_11','val_12']},
"Master_03": {'key_07': ['val_13','val_14'], ['key_08': ['val_15','val_16'], 'key_09': ['val_17','val_18']}
}
What I've got so far is the sub dict:
import itertools
master_dic = {}
servant_dic = {}
keys = []
values = []
for line in data_long:
for item in line:
keys.extend(item[:1])
values.append(item[1:])
servant_dic = dict(itertools.izip(keys, values))
Which puts out a dictionary, as expected.
servant_dic = {
'key_06': ['val_11','val_12'], 'key_04': ['val_08','val_07'], 'key_05': ['val_09','val_10'],
'key_02': ['val_03','val_04'], 'key_03': ['val_05','val_06'], 'key_01': ['val_01','val_02']
}
The problem is, that if I want to add the master_keys to this dictionary, so I get the wanted result, I'd have to do this in a certain order, which would be possible, if each line had a counter like this:
enumerated_dic =
{
0: {'key_01':['val_01','val_02'],'key_02': ['val_03','val_04'], 'key_03': ['val_05','val_06']},
1: {'key_04': ['val_07','val_08'], 'key_05': ['val_09','val_10'], 'key_06': ['val_11','val_12']},
2: {'key_07': ['val_13','val_14'], ['key_08': ['val_15','val_16'], 'key_09': ['val_17','val_18']}
}
I'd love to do this with enumerate(), while each line of the servant_dic is build, but can't figure out how. Since afterwards, i could simply replace the counters 0, 1, 2 etc. with the master_keys.
Thanks for your help.
master_keys = ["Master_01", "Master_02", "Master_03"]
data_long = [[['key_01','val_01','val_02'],['key_02','val_03','val_04'], ['key_03','val_05','val_06']],
[['key_04','val_07','val_08'], ['key_05','val_09','val_10'], ['key_06','val_11','val_12']],
[['key_07','val_13','val_14'], ['key_08','val_15','val_16'], ['key_09','val_17','val_18']]]
_dict = {}
for master_key, item in zip(master_keys, data_long):
_dict[master_key] = {x[0]: x[1:] for x in item}
print _dict
Hope this will help:
{master_key: {i[0]: i[1:] for i in subkeys} for master_key, subkeys in zip(master_keys, data_long)}
My functional approach:
master_dic = dict(zip(master_keys, [{k[0]: k[1::] for k in emb_list} for emb_list in data_long]))
print(master_dic)
You can also use pop and a dict comprehension:
for key, elements in zip(master_keys, data_long):
print {key: {el.pop(0): el for el in elements}}
...:
{'Master_01': {'key_02': ['val_03', 'val_04'], 'key_03': ['val_05', 'val_06']}}
{'Master_02': {'key_06': ['val_11', 'val_12'], 'key_04': ['val_07', 'val_08'], 'key_05': ['val_09', 'val_10']}}
{'Master_03': {'key_07': ['val_13', 'val_14'], 'key_08': ['val_15', 'val_16'], 'key_09': ['val_17', 'val_18']}}

Categories

Resources