4
\$\begingroup\$

I have a list of dictionaries and its elements has id and parent_id fields.

Main purposes:

  • If the parent_id field of an element is defined, it should be returning the rest of elements except itself.
  • If the parent_id field of element is not defined, it should be returning the rest of elements. In other words, its all child elements. Because it is parent element.

I'll be sharing my implementation below. But I need more concise and Pythonic way.

products = [
    {"id": 5, "counter": 10, "parent_id": None},
    {"id": 6, "counter": 10, "parent_id": 5},
    {"id": 7, "counter": 10, "parent_id": 5},
]

def get_by_id(product_id):
    product = list(filter(lambda p: p["id"] == product_id, products))
    return product[0] if product else False

def get_by_product(product):
    p = []
    for i in products:
        if product["parent_id"]:
            if i["id"] == product["parent_id"] or i["id"] != product["id"]:
                p.append(i)
        else:
            if i["parent_id"] == product["id"]:
                p.append(i)
    return p

p = get_by_id(7)
g = get_by_product(p)
print(g) # [{'id': 5, 'counter': 10, 'parent_id': None}, {'id': 6, 'counter': 10, 'parent_id': 5}]

p = get_by_id(5)
g = get_by_product(p)
print(g) # [{'id': 6, 'counter': 10, 'parent_id': 5}, {'id': 7, 'counter': 10, 'parent_id': 5}]

I have changed ridiculous if statements above like this:

def get_by_product(product):
    p = []
    for i in products:
        if product["parent_id"] and i["id"] == product["parent_id"] or i["id"] != product["id"] or i["parent_id"] == product["id"]:
            p.append(i)
    return p 
\$\endgroup\$
2
  • 1
    \$\begingroup\$ How do you use these, because you could probably change the data to a dictionary for \$O(n)\$ creation, and \$O(1)\$ lookup, rather than \$O(n)\$ lookup. \$\endgroup\$
    – Peilonrayz
    Jan 6, 2018 at 4:07
  • \$\begingroup\$ It is not used in live environment. It was just a trivial code for practising. Open to any suggestions. \$\endgroup\$
    – vildhjarta
    Jan 6, 2018 at 13:26

1 Answer 1

3
\$\begingroup\$
  1. If your actual program has the products list is a constant global variable, declare it as PRODUCTS (uppercase global constants)
  2. Using list(filter(lambda can be removed by a simple comprehension. A list comprehension is the preferred method of iterating over lists as per PEP-0202
  3. Instead of returning False in get_by_id, return a None, as that is more user intuitive.

Check the following:

def get_by_id(product_id):
    """Return a product from the list with given id, or None if not found"""
    return next((p for p in PRODUCTS if p["id"] == product_id), None)

There is no extra list being created in-memory. The generator expression returns the first value (if any) or defaults to the None. Check docs for the next function.

For the get_by_product, you can have 2 snippets. One will remove the given product from list if product.parent_id exists, and another will search for child products.

def get_by_product(product):
    if product["parent_id"] is not None:
        return [p for p in PRODUCTS if p != product]
    return [p for p in PRODUCTS if p['parent_id'] == product['id']]
\$\endgroup\$
5
  • \$\begingroup\$ Do you have any source which explains the speed of list comprehensions over filter function? \$\endgroup\$
    – vildhjarta
    Jan 6, 2018 at 14:12
  • 1
    \$\begingroup\$ @vildhjarta stackoverflow.com/a/3013686/1190388 \$\endgroup\$
    – hjpotter92
    Jan 6, 2018 at 14:25
  • \$\begingroup\$ if you add another product tree you can see the bug. if the product is not None, it returns all dictionaries except itself. \$\endgroup\$
    – vildhjarta
    Jan 8, 2018 at 20:39
  • 1
    \$\begingroup\$ You could simplify the get_by_id function, by using the default parameter to the next() function as specified here. return next((p for p in PRODUCTS if p["id"] == product_id), None) instead would be sufficient. \$\endgroup\$
    – radzak
    Mar 18, 2019 at 8:34
  • \$\begingroup\$ @Jatimir That is indeed better. Updated my code above. Thanks :) \$\endgroup\$
    – hjpotter92
    Mar 18, 2019 at 9:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.