Search code examples
pythonnested-lists

Count the number of times a value exists in arbitrary nested lists


I have a json data like this:

{
    "children": [{
                "objName": "Sprite1",
                "scripts": [[89, 68, [["whenGreenFlag"], ["doForever", [["doIf", ["keyPressed:", "space"], [["wait:elapsed:from:", 0.5], ["playSound:", "meow"]]],
                                    ["doIf", ["mousePressed"], [["playDrum", 1, 0.25]]]]]]]],
                "sounds": [{
                        "soundName": "meow",
                        "soundID": 0,
                        "md5": "83c36d806dc92327b9e7049a565c6bff.wav",
                        "sampleCount": 18688,
                        "rate": 22050,
                        "format": ""
                    }],

        }
}

I want to count of number of occurrences of "keyPressed" under "scripts". But I'm not sure how to iterate through the list of lists of lists.... under "scripts".

This is my code:

import simplejson as json

with open("D:\\1.SnD\Work\PyCharmProjects\project.json", 'rb') as f:
    json_data = json.loads(str(f.read(), 'utf-8'))
    key_presses = []
    for child in json_data.get('children'):
        for script in child.get('scripts'):
            for mouse in script.get("keyPressed"): // Does not work
                print(mouse)

I want to store the count of keyPressed in key_presses list.


Solution

  • Borrowing the excellent flatten method from What is the fastest way to flatten arbitrarily nested lists in Python? and combining it with Counter from collections, you get:

    import collections, json
    
    def flatten(container):
        for i in container:
            if isinstance(i, list) or isinstance(i, tuple):
                for j in flatten(i):
                    yield j
            else:
                yield i
    
    with open("D:\\1.SnD\Work\PyCharmProjects\project.json", 'rb') as f:
        json_data = json.loads(str(f.read(), 'utf-8'))
    
    print(collections.Counter(
           flatten(json_data['children'][0]['scripts']))['keyPressed:'])
    

    If you run the above, the output will be the number of times keyPressed: appears in scripts.