Как расширить это понимание вложенного списка в Python - PullRequest
0 голосов
/ 16 октября 2018

Рассмотрим следующую функцию:

Он принимает список списков в качестве входных данных и находит все комбинации элементов из каждого из этих списков.

def product(llist):
    result = [[]]

    for lst in llist:
        result = [x + [y] for x in result for y in lst]

    return result

Например:

product([[1,2], [3], [4,5]])

вернется:

[[1, 3, 4], [1, 3, 5], [2, 3, 4], [2, 3, 5]]

Я пытаюсь понять, как работает эта функция, и, следовательно, пытаюсь расширить понимание списка.

Вот попытка:

def product2(llist):
    result = [[]]
    for lst in llist:
        for x in result:
            result = []
            for y in lst:
                result.append(x+[y])

    return result

это не дает мне правильный результат, оно возвращает:

[[2, 3, 4], [2, 3, 5]]

и я понимаю этот неверный результат согласно определению product2.Но я не могу расширить исходную функцию product, чтобы понять, как она работает.

Может ли кто-нибудь разработать понимание вложенного списка в функции product?

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Помогает, если вы печатаете частичные значения result, например так:

def product(llist):
    result = [[]]

    for lst in llist:
        result = [x + [y] for x in result for y in lst]
        print(result)

    return result

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

[[1], [2]]

Затем во втором проходе каждый внутренний список в результате будет заменен на себя, плюс каждый элемент во втором внутреннем списке, переданный как параметр:

[[1, 3], [2, 3]]

И затем, когда у вас есть внутренний список параметров с более чем одним элементом, он будет реплицировать текущие существующие внутренние списки в результате

[[1, 3, 4], [1, 3, 5], [2, 3, 4], [2, 3, 5]]

Это происходит так, потому что в одномпройти через понимание списка, рассматриваемый список не будет обновлен.Он будет обновлен только в конце понимания.

Другой способ, которым вы могли бы видеть это, похож на сетку:

------------------
|    |  1  |  2  |
------------------
| [] | [1] | [2] |
------------------

result = [[1],[2]]

---------------
|     |   3   |
---------------
| [1] | [1,3] |
---------------
| [2] | [2,3] |
---------------

result = [[1,3],[2,3]]

-----------------------------
|       |    4    |    5    |
-----------------------------
| [1,3] | [1,3,4] | [1,3,5] |
-----------------------------
| [2,3] | [2,3,4] | [2,3,5] |
-----------------------------

result = [[1,3,4],[2,3,4],[1,3,5],[2,3,5]]

Учитывая это, версия без понимания потребуетвременная переменная для хранения обновленных значений:

def product2(llist):
    result = [[]]
    for lst in llist:
        temp_res = []
        for x in result:
            for y in lst:
                temp_res.append(x+[y])
        result = temp_res

    return result
0 голосов
/ 16 октября 2018

Понимание списка создает новый список для каждого элемента в lst и создает новые новые списки, комбинируя этот небольшой список из одного элемента со всеми списками, которые уже находятся в result.

Так, например, если result = [ [1, 2], [3, 4] ] и lst = [10, 11], новый результат будет [[1, 2, 10], [1, 2, 11], [3, 4, 10], [3, 4, 11]].

И делает это для каждого lst в llist:

def product2(llist):
    result = [[]]
    for lst in llist:
        new_result = [] # let's manually build out new result
        for existing in result:            
            for element in lst:
                new_result.append(existing + [element])
        result = new_result # update result for next lst
    return result
...