Home > Software design >  get a nested dictionary items recursively
get a nested dictionary items recursively

Time:09-17

I have a dictionary like below and I want to write a recursive function to return all products:

category = {'name': 'electronic_devices',
            'sub_categories': [
                {
                    'name': 'mobile-phone',
                    'sub_categories': [],
                    'products': [
                        'Sony xperia 1'
                        'Samsung Galaxy A32',
                        'Apple iphone 12',
                        'Xiaomi redmi 9'
                    ]
                },
                {
                    'name': 'laptop',
                    'sub_categories': [
                        {
                            'name': 'ultrabook',
                            'sub_categories': [],
                            'products': [
                                'Asus ROG strix',
                                'Microsoft surface book 3',
                                'Lenovo ideapad 3'
                            ]
                        }
                    ],
                    'products': [
                        'Dell inspiron 3583-5278',
                        'HP pavilion dk1056wm'
                    ]
                }
            ],
            'products': []
            } 

my function is:

def get_product(dic):
    for k, v in dic.items():
        if k == 'sub_categories':
            return get_product(k)
        elif k == 'products':
            return v
   
print(get_product(category))

This function ends up with error. can anyone help me find the problem?

CodePudding user response:

You have to iterate like this:

def get_product(dic):
    x = []
    for k, v in dic.items():
        if k == 'sub_categories':
            for i in v:
                x.extend(get_product(i))
        elif k == 'products':
            x.extend(v)
    return x
   
print(get_product(category))

Output:

['Sony xperia 1Samsung Galaxy A32', 'Apple iphone 12', 'Xiaomi redmi 9', 'Asus ROG strix', 'Microsoft surface book 3', 'Lenovo ideapad 3', 'Dell inspiron 3583-5278', 'HP pavilion dk1056wm']

CodePudding user response:

A solution that doesn't use recursion. You can just use a queue for this purpose. This would also work no matter how nested your data is.

category = {
    'name': 'electronic_devices',
    'sub_categories': [
        {
            'name': 'mobile-phone',
            'sub_categories': [],
            'products': [
                'Sony xperia 1',
                'Samsung Galaxy A32',
                'Apple iphone 12',
                'Xiaomi redmi 9'
            ]
        },
        {
            'name': 'laptop',
            'sub_categories': [
                {
                    'name': 'ultrabook',
                    'sub_categories': [
                        {
                            'products': [
                                'Laser sword',
                                'Beyblade',
                                'Crush Gear'
                            ]
                        }
                    ],
                    'products': [
                        'Asus ROG strix',
                        'Microsoft surface book 3',
                        'Lenovo ideapad 3'
                    ]
                }
            ],
            'products': [
                'Dell inspiron 3583-5278',
                'HP pavilion dk1056wm'
            ]
        }
    ],
    'products': ["Solar System Destructor Beta-3A"]
}

def get_products(dic):
    products = []
    queue = [dic]
    
    while queue:
        data = queue.pop()
        if isinstance(data, dict):
            products.extend(data.get('products', []))
            queue.extend(data.values())
        elif isinstance(data, list):
            queue.extend(data)

    return products

print(get_products(category))

Output

['Solar System Destructor Beta-3A', 'Dell inspiron 3583-5278', 'HP pavilion dk1056wm', 'Asus ROG strix', 'Microsoft surface book 3', 'Lenovo ideapad 3', 'Laser sword', 'Beyblade', 'Crush Gear', 'Sony xperia 1', 'Samsung Galaxy A32', 'Apple iphone 12', 'Xiaomi redmi 9']

CodePudding user response:

You should not access dictionary values by iterating through key-value pairs and matching the keys as it is inefficient and unnecessarily verbose. Access dictionary values directly by keys instead:

def get_product(d):
    return [p for s in d['sub_categories'] for p in get_product(s)]   d['products']

so that get_product(category) returns:

['Sony xperia 1Samsung Galaxy A32', 'Apple iphone 12', 'Xiaomi redmi 9', 'Asus ROG strix', 'Microsoft surface book 3', 'Lenovo ideapad 3', 'Dell inspiron 3583-5278', 'HP pavilion dk1056wm']
  • Related