Dict in List comprehension Python - python

I have a List with API results:
result = [(True,
{'result':
{'skus':
[{'sku': '123'}, {'sku': '124'}]
}
}
),
(True,
{'result':
{'skus':
[{'sku': '125'}, {'sku': '126'}]
}
}
)
]
So, I need to get each 'sku'
I can do it in two loops:
for elem in result:
for sku in elem[1]["result"]["skus"]:
print(sku)
How can I do it in one string?

How can I do it in one string?
Is this what you're looking for?
print([sku for elem in result for sku in elem[1]["result"]["skus"]])

You can use a list comprehension to extract all the 'sku' values from the result list in a single line of code.
result = [(True, {'result': {'skus': [{'sku': '123'}, {'sku': '124'}]
}
}
),
(True,
{'result':
{'skus':
[{'sku': '125'}, {'sku': '126'}]
}
}
)
]
skus = [sku['sku'] for elem in result for sku in elem[1]['result']['skus']]
print(skus)
This will print a list of all the 'sku' values:
['123', '124', '125', '126']
The list comprehension is essentially a shorthand way of writing the nested for-loops in a single line. The output of the list comprehension is a list of all the 'sku' values extracted from the 'result' list.

Linear time complexity with one for-loop:
[result[x][1]['result']['skus'] for x,y in enumerate(result)]
#[[{'sku': '123'}, {'sku': '124'}], [{'sku': '125'}, {'sku': '126'}]]
Edit as suggested by #buran
[item[1]['result']['skus'] for item in result]

Related

python: search in list of lists of dictionaries

I want to iterate over a list of lists of dictionaries:
data = [
{'name': 'sravan'},
{'name': 'bobby'},
{'name': 'ojsawi', 'number': '123'},
{'name': 'rohith', 'number': '456'},
{'name': 'gnanesh', 'number': '123'}
]
Furthermore I want to check each entry if there is a key number where the value is 123.
If so, I want to append the value of name of this entry in a new list
which would be 'ojsawi' and 'gnanesh' in the above case.
Else, I want to append 0 in the new list.
This means, the final new_list with the appended values should look like this:
new_list = {0, 0, 'ojsawi', 0, 'gnanesh'}
I have tried different versions/possibillities with 2D for loops and lambdas etc. but I think the main problem is that the lists have different sizes. Any help/tipps would be much appreciated.
You can define it with list comprehensions with a nested if/else in it:
new_list = [x.get('name') if x.get('number') == '123' else 0 for x in data]
Outputting:
[0, 0, 'ojsawi', 0, 'gnanesh']
Other than list comprehensions, you can also do it using map() and functional programming if you want. Note that map() returns an iterator which generates things as you go if you are using a for loop, so if you want the entire result immediately, use list() around your map() function.
def zerofilter(my_dict):
number = my_dict.get("number")
if number != "123":
return 0
else:
return my_dict.get("name")
data = [
{'name': 'sravan'},
{'name': 'bobby'},
{'name': 'ojsawi', 'number': '123'},
{'name': 'rohith', 'number': '456'},
{'name': 'gnanesh', 'number': '123'}
]
print(list(map(zerofilter, data))) # output is [0, 0, 'ojsawi', 0, 'gnanesh']
# You can also do this:
for res in map(zerofilter, data):
print(res)

Remove dictionary from list if it contains forbidden value

I have a list of dictionaries:
my_dicts = [
{'name': 'aaa',
'codename': 'bbbb',
'type': 'cccc',
'website': 'url1'},
{'name': 'aaa2',
'codename': 'bbbb2',
'type': 'cccc2',
'product_url': 'url2'},
{'name': 'aaa2',
'codename': 'bbbb2',
'type': 'cccc2',
'dop_url': 'url3'}
]
and a list:
my_list = ['url1', 'url3']
My goal is to have this output:
my_dicts = [
{'name': 'aaa2',
'codename': 'bbbb2',
'type': 'cccc2',
'product_url': 'url2'}
]
I want to find the most efficient way to remove the dictionaries where any value of said dictionary is in a list.
I tried this, but I'm getting the following error: RuntimeError: dictionary changed size during iteration.
for url in my_list:
for e in my_dicts:
for key, value in e.items():
if value == url:
del e[key]
You can use a list comprehension with all(), retaining only the dictionaries that do not have a key-value pair where the value appears in my_list:
[item for item in my_dict if all(url not in item.values() for url in my_list)]
This outputs:
[{'name': 'aaa2', 'codename': 'bbbb2', 'type': 'cccc2', 'product_url': 'url2'}]
One approach is to have an outer loop that loops over each element in the list my_dicts and to have an inner loop that loops over each element of a given dict. For a given iteration of the outer loop, we store the index of the dict inside my_dicts inside the indices list if one of the values in the dict is contained in my_list. After completing our scan over my_dicts, using the indices we know which elements of my_dicts to remove.
indices = []
# locate dicts with a value that is in my_list
for index, elem in enumerate(my_dicts):
for key in elem:
if elem[key] in my_list:
indices.append(index)
break
# remove dicts
for i in reversed(indices):
my_dicts.pop(i)
print(my_dicts)
Output
[{'name': 'aaa2', 'codename': 'bbbb2', 'type': 'cccc2', 'product_url': 'url2'}]
I hope this helps!

Pars values from lists of dictionaries

I have a list of multiple dictionaries (just one of many dictionaries in my list included below) that all have a single value I would like to extract, in the case it would be 'owner'
[
{'Key': 'owner', 'Value': 'connected#work.com'
},
{'Key': 'email_manager', 'Value': 'kort#work.com'
},
{'Key': 'boundary_id', 'Value': '344738728075'
},
}
]
Because owner is the actual value of 'Key' and the value of key 'Value' is the other piece of information needed im having a really hard time getting the desired output, something like:
owner: connected#work.com
I would like to only get that return for all my dictionaries in my list of dictionaries. For context the other dictionaries in my list follow the same formate as what is described.
I think this should work:
keys = []
values = []
for elem in arr:
keys.append(elem['Key'])
values.append(elem['Value'])
new_dict = dict(zip(keys, values))
Try this :
lst_dict = [
{'Key': 'owner', 'Value': 'connected#work.com'},
{'Key': 'email_manager', 'Value': 'kort#work.com'},
{'Key': 'boundary_id', 'Value': '344738728075'}
]
new_lst_dict = [{value['Key'] : value['Value'] for value in lst_dict}]
print(new_lst_dict)
# Output :
# [{'owner': 'connected#work.com','email_manager': 'kort#work.com', 'boundary_id': '344738728075'}]

How to get dictionary value from key in a list?

I am trying to create a new list from a list of dictionary items.
Below is an example of 1 dictionary item.
{'id': 'bitcoin',
'symbol': 'btc',
'name': 'Bitcoin',
'current_price': 11907.43,
'market_cap': 220817187069,
'market_cap_rank': 1}
I want the list to just be of the id item. So what I am trying to achieve is a list with items {'bitcoin', 'etc', 'etc}
You can use list comprehension:
my_list = [{'id': 'bitcoin', 'symbol': 'btc', ...}, ...]
[d['id'] for d in my_list]
Which translates to : for each dictionary in my_list, extract the 'id' key.
id_list = [d["id"] for d in dictlist ]
This should work for you
list = [ i['id'] for i in list_of_dict]
this should help
Simple and readable code that solves the purpose:
main_list = []
for item in main_dict:
main_list.append(item.get("id", None))
print(main_list)

python, map name from a list to a list of dict

I have the following list and list of dicts:
data = [dict(position=1, value=150.3),
dict(position=0, value=28.5),
dict(position=2, value=1050.3)]
names = ["CL", "ES", "EUR"]
I would like to map the values of the list into the list of dicts so they match the value stated in the key "position" of the dict - to get the following result:
data = [dict(name="ES", position=1, value=150.3),
dict(name="CL", position=0, value=28.5),
dict(name="EUR", position=2, value=1050.3)]
Is there any "smart" and pythonic way to achieve that?
First of all, please present your question in actual Python form. dict is a type; the way you represent dictionaries in Python is with {}.
Also, you don't have "a dict and list", you have two lists, one of which consists of three dictionaries. So:
data = [
{'position': 1, 'value': 150.3},
{'position': 0, 'value': 28.5},
{'position': 2, 'value': 1050.3}
]
names = ["CL", "ES", "EUR"]
So, given that you do have lists, there is no concern about ordering. A simple loop will give you what you want:
for d in data:
d['name'] = names[d['position']]
This updates data in place:
>>> data
[{'position': 1, 'name': 'ES', 'value': 150.3}, {'position': 0, 'name': 'CL', 'value': 28.5}, {'position': 2, 'name': 'EUR', 'value': 1050.3}]
You can use a list comprehension and dictionary update:
data = [dict(position = 2, value=150.3),
dict(position = 1, value = 28.5),
dict(position=3, value=1050.3)]
names = ['CL', 'ES', 'EUR']
# Sort names according to "position" value of the dictionary
sorted_names = [names[idx] for idx in map(lambda x: x['position'], data)]
# Update modifies inplace
_ = [data[idx].update({'name' : el}) for idx, el in enumerate(sorted_names)]
Which gives the expected output:
data
[{'name': 'ES', 'position': 2, 'value': 150.3},
{'name': 'CL', 'position': 1, 'value': 28.5},
{'name': 'EUR', 'position': 3, 'value': 1050.3}]
You could try:
data = [{"position": 2, "value": 150},
{"position": 1, "value": 200}]
names = ["CL", "ES"]
for item in data:
item["name"] = names[item["pos"] - 1]
Where we go through all the dictionaries in the list, then for each dictionary we set the "name" key to be equal to the value in data at the position described in item["pos"] minus 1.
This of course assumes your data is clean and all items in data correctly map to items in names.
If this is not the case, use a try-except:
for item in data:
try:
item["name"] = names[item["pos"] - 1]
except IndexError:
item["name"] = None
You can also use the update method on the dictionary elements in the list, if you like the keyword-argument convention, as the style of your question suggests.
for item in data:
item.update(name=names[item["position"]])
A one liner implementation using list comprehension.
print [dict(d.items()+[('name',names[d['position']-1])]) for d in data]

Categories