Понимание вложенного списка с помощью оператора if - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь разобраться в понимании вложенного списка и прочитал превосходное объяснение здесь .

Проблема, которую я имею при переводе, заключается в том, что у меня есть if предложение в моем внутреннем цикле, и я не вижу, как применить это к шагу func(), поскольку я теряю счетчик, который я получаю от enumerate(), когда я перехожу из вложенных циклов в список для понимания.

nested_list = [[{'a': 1, 'b': 2}, {'c': 3, 'd': 4}], [{'a': 5, 'b': 6}, {'c': 7, 'd': 8}]]
new_list = []
for c, x in enumerate(nested_list):
    for d, y in enumerate(x):
        if d == 1:
            new_list.append(y)
print(new_list)
[{'c': 3, 'd': 4}, {'c': 7, 'd': 8}]

Понимание вложенного списка может выглядеть примерно так:

new_list = [if ??? y
               for x in nested_list
                   for y in x]

... но я не могу понять / подумать, как получить предложение, так как у меня нет счетчика при понимании вложенного списка.

Есть ли способ достичь этого или я должен придерживаться подхода с вложенными циклами?

Ответы [ 4 ]

0 голосов
/ 27 сентября 2018
print ([ y for c, x in enumerate(nested_list) for d, y in enumerate(x) if d == 1])
0 голосов
/ 27 сентября 2018

когда я теряю счетчик, я получаю от enumerate(), когда я перехожу из вложенных циклов к списку для понимания.

Тогда почему вы его уронили?Для понимания списка все равно могут использоваться все те же итераторы, что и для цикла for.

У меня есть предложение if во внутреннем цикле, и я не вижу, как его применить

Просто положите его на то же место.Понимания списка следуют одному и тому же вложенному порядку как для циклов for, так и для фильтров if;Ваш цикл можно отобразить напрямую, удалив двоеточия : и переместив деталь в вызове .append(...) вперед:

new_list = [y   # from new_list.append(y)
    for c, x in enumerate(nested_list)   # removed the :
        for d, y in enumerate(x)         # removed the :
            if d == 1]                   # removed the :

Однако вы можете отбросить первый enumerate(), потому что выне используйте c.Вы также можете удалить второй цикл и enumerate(), потому что вместо этого вы можете использовать indexing :

new_list = [x[1] for x in nested_list]

Вам не нужно перебирать все значения в x здесь,это не очень эффективный метод для получения этого значения.

Если ваша проблема в том, что список x может быть на короче и не иметь элемента с индексом 1, отфильтруйте эти вложенныесписки по длине сначала:

new_list = [x[1] for x in nested_list if len(x) > 1]
0 голосов
/ 27 сентября 2018

Вам нужен второй элемент для каждого массива в списке, поэтому вы можете сделать что-то вроде этого:

new_list = [nested_list[i][1] for i in range(len(nested_list))]

еще лучше

new_list  = [x[1] for x in nested_list]
0 голосов
/ 27 сентября 2018

вы можете переписать это следующим образом:

new_list = [y for x in nested_list for d, y in enumerate(x) if d == 1]

циклы в «естественном» порядке, и условие в конце.Включайте y, только если d==1

один возможный результат (поскольку дикты не упорядочены):

[{'c': 3, 'd': 4}, {'c': 7, 'd': 8}]

Обратите внимание, что в вашем случае это проще и эффективнее (O(n) против O(n**2)) записать:

new_list = [x[1] for x in nested_list]

единственное отличие состоит в том, что если x слишком короткий, последний код будет нарушен, поэтому, возможно, длина теста:

new_list = [x[1] for x in nested_list if len(x)>1]
...