Подтвердить что ты не робот

Как создать список или кортеж пустых списков в Python?

Мне нужно поэтапно заполнить список или кортеж списков. Что-то похожее на это:

result = []
firstTime = True
for i in range(x):
    for j in someListOfElements:
        if firstTime:
            result.append([f(j)])
        else:
            result[i].append(j)

Чтобы сделать его менее подробным, более элегантным, я подумал, что предварительно распределю список пустых списков

result = createListOfEmptyLists(x)
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)

Часть preallocation для меня не очевидна. Когда я делаю result = [[]] * x, я получаю список x ссылок на один и тот же список, так что вывод следующих

result[0].append(10)
print result

является:

[[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]]

Я могу использовать цикл (result = [[] for i in range(x)]), но мне интересно, существует ли "петлевое" решение.

Это единственный способ получить то, что я ищу.

4b9b3361

Ответ 1

result = [list(someListOfElements) for _ in xrange(x)]

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

Если это имеет смысл, рассмотрите возможность использования copy.deepcopy(someListOfElements)

Генераторы и список понятий и вещей считаются вполне pythonic.

Ответ 2

На самом деле нет способа создать такой список без какого-либо цикла. Существует несколько способов скрытия цикла, но, как и [[]] * x, скрывает цикл. Там понимается список, который "скрывает" цикл в выражении (бит его, к счастью, все еще очевиден.) Там также map(list, [[]]*x), у которого есть две скрытые петли (одна в [[]] * x и одна в map, которая создает копию каждого списка, используя list().)

Также существует возможность не создавать список списков заранее. Другие ответы уже охватывают простой подход, но если это как-то не соответствует вашим потребностям, есть другие способы. Например, вы можете создать функцию, которая при необходимости добавляет пустой список в список result и вызывает это:

def append(L, idx, item):
    while len(L) <= idx:
        L.append([])
    L[idx].append(item)

for i in range(x):
    for j in someListOfElements:
        append(result, i, j)

Или вы можете использовать collections.defaultdict(list) вместо списка:

import collections
result = collections.defaultdict(list)
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)

Это имеет смысл использовать уже существующий тип, который меньше работает, но это означает, что теперь у вас есть dict (индексированный целыми числами) вместо списка, который может быть или не быть тем, что вы хотите. Или вы можете создать класс, который ведет себя почти как список, но добавляет новые списки в себя вместо повышения индекса IndexError, например:

import UserList
class defaultlist(UserList.UserList):
    def __getitem__(self, idx):
        while len(self) <= idx:
            self.append([])
        return UserList.UserList.__getitem__(self, idx)

result = defaultlist()
for i in range(x):
    for j in someListOfElements:
        result[i].append(j)

Ответ 3

Вы можете написать функцию быстрого генератора. У этого было бы другое использование, кроме этого конкретного случая, поэтому я немного его обобщу. Dig this:

def create(n, constructor=list):
    for _ in xrange(n):
        yield constructor()

Затем, чтобы составить список списков,

result = list(create(10))

чтобы составить список пустых dicts,

result = list(create(20, dict))

и (для полноты), чтобы составить список пустых Foos,

result = list(create(30, Foo))

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

Последнее состоит в том, что, поскольку единственное требование, которое мы ставим на constructor, состоит в том, что оно может быть вызываемым, вы даже можете передать ему все, что возвращает то, что вы хотите в своем списке. Связанный метод, который извлекает результаты из запроса базы данных, например. Это довольно полезная небольшая три строки кода.

Ответ 4

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

result = []
for i in range(x):
    result.append([])
    for j in someListOfElements:
        result[i].append(j)

[Изменить: Добавить пример]

>>> someListOfElements = ['a', 'b', 'c']
>>> x = 3
>>> result = []
>>> for i in range(x):
...     result.append([])
...     for j in someListOfElements:
...         result[i].append(j)
... 
>>> 
>>> result
[['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c']]

Ответ 5

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

result = []
for i in range(x):
    data = []
    for j in someListOfElements:
        data.append(j)
    # or data = [j for j in someListOfElements]
    result.append(data)

Ответ 6

Попробуйте использовать list() вместо [], я думаю, что создаст новый экземпляр.