Reputation: 38502
I have multi level list of dictionary from which I need to make two required list. Currently I can do it this way but wanted to make fully list comprehension way,
poi = []
nh = []
tr_poi_nh = response.xpath('string(//body)').re(r'window\.__WEB_CONTEXT__=(.*?);\(this')[0]
tr_poi_nh = json.loads(tr_poi_nh.replace("pageManifest", '"pageManifest"'))
for entry in tr_poi_nh['pageManifest']['hydrations']:
if entry['package'] == 'e374ol':
for value in entry['props']['initialAvailableFilters']:
if value['paramName'] =='distFrom':
poi = [x['normalized_name'] for x in value['poiSet']]
if value['paramName'] == 'zfn':
nh = [y['label'] for y in value['choices']]
print(poi,nh)
Upvotes: 0
Views: 96
Reputation: 5183
As g.d.d.c mentioned it is not always the case that a list comprehension will be advantageous. In this case it will have better performance because you will avoid calling append
on each iteration, as explained by this answer. If you make good use of indentation you can still have a easily readable list comprehension.
The only problem is, you cannot return two different lists from a list comprehension, the closest you could get is to return a single list with (poi, nh)
pairs, where poi
and nh
are lists.
Another consideration which is not clear in your question is if you want to append
or extend
each list.
Anyway here is the list comprehension. You can tell it is basically the inner-most code first then all the for
s and if
s in order.
main_list = [
(
[x['normalized_name'] for x in value['poiSet']]
if value['paramName'] == 'distFrom' else []
,
[y['label'] for y in value['choices']]
if value['paramName'] == 'znf' else []
)
for entry in tr_poi_nh['pageManifest']['hydrations']
if entry['package'] == 'e374ol'
for value in entry['props']['initialAvailableFilters']
]
I would think about which is easiest from here, either to use main_list
as it is and modify further code, or separate the tuples into two lists.
If you MUST have poi
and nh
as two separate lists, you now need two list comprehensions.
# to have lists of lists
poi = [x[0] for x in main_list]
nh = [x[1] for x in main_list]
# OR
# to have flat lists
poi = [e for x in main_list for e in x[0]]
nh = [e for x in main_list for e in x[1]]
Upvotes: 1
Reputation: 2941
I agree with g.d.d.c's comment. Code readability is highly wanted.
On another note, it looks like you're overriding poi
and nh
at with the suggested approach.
I'm guessing this will give you a more wanted approach:
poi = []
nh = []
tr_poi_nh = response.xpath('string(//body)').re(r'window\.__WEB_CONTEXT__=(.*?);\(this')[0]
tr_poi_nh = json.loads(tr_poi_nh.replace("pageManifest", '"pageManifest"'))
for entry in tr_poi_nh['pageManifest']['hydrations']:
if entry['package'] == 'e374ol':
for value in entry['props']['initialAvailableFilters']:
if value['paramName'] =='distFrom':
poi.extend([x['normalized_name'] for x in value['poiSet']])
if value['paramName'] == 'zfn':
nh.extend([y['label'] for y in value['choices']])
print(poi,nh)
By using extend you will add all of the values to your original list rather then override the entire list.
Upvotes: 1