0

I have rather lengthy nested conditionals that are an eyesore. I've tried to turn it into a list comprehension, but failed. I'm not even sure if it's feasible to create such list comprehension. My question is how I can turn the script below into a list comprehension, or perhaps I should leave it as is?

Note: The current script works just fine. The logs coming from the server are really long, so a sample here is not possible.

group_name_list = []
for gn in query_res['hits']['hits']:
    if 'user' not in gn['_source']:
        group_name_list.append('-')
    else:
        gn['_source']['user']
        if 'target' not in gn['_source']['user']:
            group_name_list.append('-')
        else:
            gn['_source']['user']['target']
            if 'group' not in gn['_source']['user']['target']:
                group_name_list.append('-')
            else:
                gn['_source']['user']['target']['group']
                if 'name' not in gn['_source']['user']['target']['group']:
                    group_name_list.append('-')
                else:
                    group_name_list.append(gn['_source']['user']['target']['group']['name'])

Output:

['-', '-', '-', '-', 'Endpoint1', 'PublicWiFi', 'Accounting', 'MobileVPN', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-']
  • 4
    The statements in the lines following `else:` like `gn['_source']['user']` are useless, so you can just omit them and then you can merge `else: if:` to `elif:` and get rid of the indentation. – mkrieger1 Apr 18 '23 at 15:48
  • Actually this can be done with single try/except – buran Apr 18 '23 at 15:52
  • 1
    Some of the recipes in the answers here may be useful: https://stackoverflow.com/questions/25833613/safe-method-to-get-value-of-nested-dictionary – slothrop Apr 18 '23 at 15:55

2 Answers2

3

You could do this with a list comprehension

group_name_list = [gn.get('_source', {}).get('user', {}).get('target', {}).get('group', {}).get('name', '-') for gn in query_res['hits']['hits']]

but a for loop (using a slight refactoring of Vojtěch Chvojka' answer catching KeyError) is easier to read:

group_name_list = []
for gn in query_res['hits']['hits']:
    try:
        name = gn['_source']['user']['target']['group']['name']
    except KeyError:
        name = '-'
    group_name_list.append(name)
chepner
  • 497,756
  • 71
  • 530
  • 681
2

I don't think that list comprehension would make that better. But the ifs can be merged into one. That could improve it.:

group_name_list = []
for gn in query_res['hits']['hits']:
    if 'user' in gn['_source']
            and 'target' in gn['_source']['user']
            and 'group' in gn['_source']['user']['target']
            and 'name' in gn['_source']['user']['target']['group']:
        group_name_list.append(gn['_source']['user']['target']['group']['name'])
    else:
        group_name_list.append('-')

Or wrap that into try-except:

group_name_list = []
for gn in query_res['hits']['hits']:
    try:
        group_name_list.append(gn['_source']['user']['target']['group']['name'])
    except KeyError:
        group_name_list.append('-')
Vojtěch Chvojka
  • 378
  • 1
  • 15