0

I have a dict from a json API call that looks like this:

{
  'id': '63d08d5c57abd98fdeea7985',
 'pageName': 'Some Page Name',
  'bodyContent':
    [{
      'children': [{
        'alpha': 'foo foo foo',
        'beta': 'bar bar bar'
        }]
    }],
 'date': '2023-01-25T02:01:00.965Z'
}

To reference the nested items inside bodyContent, I'm doing a loop within a loop (to get alpha):

{% for item in items.get('bodyContent') %}
  {% for i in item.get('children') %}
    {{ i['alpha'] }}
  {% endfor %}
{% endfor %}

I see these nested for loops in a lot of example code, but is this really the best way - a loop within a loop? I can't help but feel like it's a bit dirty and am used to other languages where a loop within a loop isn't necessary for a structure that is this basic.

Edit: What other languages am I referring to, where nested loops wouldn't be necessary? Things like array_map or array_reduce in PHP to simplify data structures (when you can't alter how they're stored, like the data in my example from an API). If nested loops are A-OK in Python then that's cool too. I'm just not sure what the common wisdom is with them in Python.

4
  • 4
    How could a nested loop not be necessary? You have a list of dictionaries inside each dictionary in an (outer) list of dictionaries, which is not exactly a "basic" data structure. Do you actually need both lists? If not, simplify your structure. If you do, accept for what it is. Commented Jan 28, 2023 at 16:51
  • 3
    In what languages could you avoid having a loop to iterate? Commented Jan 28, 2023 at 16:54
  • 1
    In what language are nested for loops not necessary for accessing arbitrary json data? Commented Jan 28, 2023 at 16:55
  • @rici I can't alter the data returned from the API, so simplifying what it gives me into a single list isn't an option. I'm used to template engines like Twig where dot notation lets you descend into child elements without explicitly writing an additional loop. Even without Twig, object reference in PHP lets you do similar things without nesting loops within loops or even using array_map or array_reduce to simplify the structure before running a single loop on it. Commented Jan 29, 2023 at 4:28

1 Answer 1

1

The loop you show in your question isn't written in Python. It's written in the Jinja template language, which really isn't all that much like Python at all.

We can solve this by providing Jinja with some filters that provide more convenient access to nested data structures. For example, if we write a JMESPath filter like this:

import jmespath

def filter_jmespath(v, expr):
    return jmespath.search(expr, v)

And provide that to Jinja, we can reduce your template to:

{{ items|jmespath('bodyContent[*].children[*].alpha[]|[0]') }}

Given the following complete example:

import jinja2
import jmespath

items = {
    "id": "63d08d5c57abd98fdeea7985",
    "pageName": "Some Page Name",
    "bodyContent": [{"children": [{"alpha": "foo foo foo", "beta": "bar bar bar"}]}],
    "date": "2023-01-25T02:01:00.965Z",
}


def filter_jmespath(v, expr):
    return jmespath.search(expr, v)


env = jinja2.Environment()
env.filters["jmespath"] = filter_jmespath

template = env.from_string(
    """
{{ items|jmespath('bodyContent[*].children[*].alpha[]|[0]') }}
"""
)

print(template.render(items=items))

We get the following output:


foo foo foo

In Python, we might write something like this (this is entered in the python REPL and assumes that your example data is stored in the variable items):

>>> next(y['alpha']
... for x in items['bodyContent']
... for y in x['children'])
'foo foo foo'
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.