1

Method check_list_comprehension have list comprehension which is returning the correct result, but I have called another method inside list comprehension code, I would like to have just one method which will return the same result.

def check_list_comprehension():
    links = [{'link': 'test.com', 'params': {}}]
    previous_url_results = [{'for_next_params': {'seckey': 'gjgJG'}}, {'for_next_params': {'seckey': 'gjfggJG'}},
                            {'for_next_params': {'seckey': 'gjgJfgggG'}}]
    links = [_operations(link, previous_url['for_next_params'])
             for link, previous_url in itertools.product(links, previous_url_results)
             if 'for_next_params' in previous_url
             ]
    print(links)


def _operations(link, y):
    link['params'] = {**link['params'], **y}
    return link

check_list_comprehension()

The output of this code:

[{'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}, {'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}, {'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}]

Please suggest a better pythonic way to do it.

drt
  • 735
  • 6
  • 16
  • I suggest to pre-filter `itertools.product(links, previous_url_results)` to `itertools.product(links, (p for p in previous_url_results if 'for_next_params' in p)` so you're not performing a product to throw it away. Reduces complexity – Jean-François Fabre Jan 11 '19 at 14:50
  • BTW the secret key is always the same. You probably need to create a copy of `link` – Jean-François Fabre Jan 11 '19 at 14:53

1 Answers1

1

first, your result is wrong: note that you get the same secret key for all items. This is because you don't copy "enough" links...

Well you can fix it by adding a copy() to your update method, but since you want it in one line, then why not rebuilding each occurrence from scratch?

Another performance issue is that you're performing the product then you filter unwanted elements out, instead of filtering the input elements.

Here's my fix for both problems:

import itertools
def check_list_comprehension():
    links = [{'link': 'test.com', 'params': {}}]
    previous_url_results = [{'for_next_params': {'seckey': 'gjgJG'}}, {'for_next_params': {'seckey': 'gjfggJG'}},
                            {'for_next_params': {'seckey': 'gjgJfgggG'}}]
    links = [{'link':link['link'], 'params':previous_url['for_next_params']}
             for link, previous_url in itertools.product(links, (p for p in previous_url_results if 'for_next_params' in p))
             ]
    print(links)

result:

[{'link': 'test.com', 'params': {'seckey': 'gjgJG'}}, {'link': 'test.com', 'params': {'seckey': 'gjfggJG'}}, {'link': 'test.com', 'params': {'seckey': 'gjgJfgggG'}}]

If params isn't empty at start, this code discards the init value. That can be fixed by changing

{'link':link['link'], 'params':previous_url['for_next_params']}

to:

{'link':link['link'], 'params':{**link['params'], **previous_url['for_next_params']}

(this kind of dictionary "addition" isn't available until python 3.5 BTW, reference: How to merge two dictionaries in a single expression?)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219