Как вы повторяете список в понимании списка?

#list #list-comprehension

#Список #понимание списка

Вопрос:

Я работаю над своими навыками понимания списка, ищу упражнения, чтобы улучшить свое понимание. Но я достиг того, что, похоже, не могу обойти. Допустим, мне нужен список всех возможных списков, содержащий 3 случайные цифры в диапазоне (1,3), при этом сумма каждого списка не равна 3.

 [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 1], [0, 2, 0] ...]
 

Очевидно, что мне нужно сделать это с помощью понимания вложенных списков. Но я не совсем уверен, как это сделать. Насколько я знаю, я не могу присвоить список переменной в понимании списка. Но мне нужна эта переменная для ссылки на выходные данные:

 list7 = [[randint(0,2) for x in range(3)] for y if sum(y) != 3]
 

Это выдает синтаксическую ошибку. Я попытался сначала присвоить внутренний список переменной, и, похоже, это тоже не сработало:

 y = [randint(0,2) for x in range(3)]
list7 = [y for y if sum(y) != 3]
 

Однако меня озадачивает то, что «y» здесь вообще не выдает ошибок. Он ведет себя так, как я ожидаю, даже если randint не присвоен «x». По-видимому, я чего-то здесь не понимаю. Итак, вот мой вопрос: как я могу повторить вложенный список в понимании списка, если я не могу присвоить его переменной в понимании? Заранее спасибо.

Комментарии:

1. Попробуйте работать изнутри, чтобы убедиться, что вы понимаете свои структуры данных и их содержимое. Понимание списков хорошо описано в документах python, включая пример, очень близкий к вашему. Кроме того, решение ваших собственных синтаксических проблем научит вас большему, чем получение ответа здесь.

2. Я не вижу смысла в переполнении стека, если единственная помощь, которую я могу получить за свое понимание, — это «иди, прочитай документацию и попробуй решить свою собственную проблему», Питер. Я делал именно это, и у меня возникли проблемы. Вот почему я пришел сюда.

3. Понимание внешнего списка не является пониманием списка list7 , потому что ничего не повторяется. Т.е. in foo предложение.

4. @PleasantNightmares жаль, что вы так думаете. как указывает @dpwrussel, in в вашем втором понимании списка нет. Некоторые вещи просто требуют много внимания, перепроверки и т. Д. Вы получите это.

Ответ №1:

Как я указал в своем комментарии, проблема с вашим решением заключается в том, что понимание внешнего списка не имеет итерации. Итак, как он узнает, сколько результатов нужно получить или когда прекратить выдачу результатов?

Существует также проблема с вашим if предложением. В вашем if you do sum(y) , который, я полагаю, должен был означать «выполнить сумму результата [randint(0,2) for x in range(3)] «. Это наоборот, потому if что выполняется первым. Кроме того, y является переменной цикла для текущего элемента в итераторе, а не результатом понимания списка для этого элемента.

Еще одна проблема с вашим решением заключается в том, что вы используете randint . Таким образом, вы можете создавать некоторые комбинации много раз, а другие — нет. Это несколько не по делу.

Я думаю, вероятно, вы хотели превратить что-то подобное в понимание списка.

 results = []
for i in range(3):
    for j in range(3):
        for k in range(3):
            if i   j   k != 3:
                results.append([i, j, k])
 

Что вполне выполнимо, но ответ заключается не в понимании вложенных списков, потому что это для случаев, когда вам нужно создавать списки списков, и в этом случае только ваш внешний список нуждается в понимании, ваши внутренние списки — это всего 3 цифры в контейнере. С таким же успехом это мог быть кортеж.

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

Итак, вы хотите сгенерировать эти 3 цифры, проверьте, составляют ли они 3, и если нет, они являются одним из элементов, которые добавляются к вашим результатам в виде списка. Вы можете воспользоваться тем фактом, что понимание списков в python поддерживает несколько итераторов, чтобы добиться того же, что и вложенные циклы for .

 results = [
    [i, j, k] 
    for i in range(3) for j in range(3) for k in range(3)
    if i   j   k != 3
]
 

Смотрите Официальные документы для получения гораздо более полезных примеров: http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions


Редактировать:

Мне пришло в голову, что то, что вы пытались сделать, это:

 results = [
    item for item in [
        [i, j, k] 
        for i in range(3) for j in range(3) for k in range(3)
    ]
    if sum(item) != 3
]
 

Который немного больше похож на ваш код. Это эквивалентно с точки зрения результатов, но может быть намного менее эффективным (как с точки зрения процесса, так и памяти), потому что в этом примере вы создаете все [i, j, k] возможности в список, а затем фильтруете их до тех, которые не суммируются до 3. Лучше вообще никогда не создавать эти списки. для этого тривиального примера это не имеет большого значения, но если [x, y, z] было дорого построить или каждый элемент использовал нетривиальные объемы памяти, это может иметь значение.

Комментарии:

1. или просто [t for t in [(x, y, z) for x in range(3) for y in range(3) for z in range(3)] if sum(t) != 3] злоупотреблять пониманием списка.

2. Это точно то же самое, что и мое альтернативное решение, просто написанное в одну строку и использующее кортеж для контейнера!