Заполните список в Python - PullRequest
4 голосов
/ 30 марта 2009

У меня есть ряд кортежей Python, представляющих координаты:

tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]

Я хочу создать следующий список:

l = []
for t in tuples:
  l[ t[0] ][ t[1] ] = something

Я получаю IndexError: список индекса вне диапазона.

Мой опыт работы с PHP, и я ожидал, что в Python вы можете создавать списки, которые начинаются с индекса> 0, то есть пробелы, а затем их заполнять, но, похоже, вы не можете.

Идея состоит в том, чтобы потом отсортировать списки. Я знаю, что могу сделать это с помощью словаря, но, насколько я знаю, словари не могут быть отсортированы по ключам. Обновление : теперь я знаю, что они могут - увидеть принятое решение.

Edit: Я хочу создать двумерный массив, который будет представлять матрицу, описанную с координатами кортежа, а затем выполнить итерацию по порядку. Если я использую словарь, у меня нет гарантии, что итерации по ключам будут в порядке -> (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) ) (2,0) (2,1) (2,2)

Может кто-нибудь помочь?

Ответы [ 9 ]

8 голосов
/ 30 марта 2009

Нет, вы не можете создать список с пробелами. Но вы можете создать словарь с ключами кортежа:

tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]
l = {}
for t in tuples:
    l[t] = something

Обновление: Попробуйте использовать NumPy , он обеспечивает широкий диапазон операций над матрицами и массивами. Cite из бесплатного pfd на NumPy, доступного на сайте (3.4.3 Индексация плоских итераторов): "Как упоминалось ранее, X.flat возвращает итератор, который будет выполнять итерацию по всему массиву (в C-смежном стиле с последним индексом) варьируется быстрее ". Похоже, что вам нужно.

6 голосов
/ 30 марта 2009

Вы должны смотреть на диктовки для чего-то подобного.

for t in tuples:
  if not l.has_key(t[0]):
    l[t[0]] = {}
  l[t[0]][t[1]] = something

Итерация по диктовке немного отличается от итерации по списку. Для этого вам понадобятся функции keys (), values ​​() и items ().

РЕДАКТИРОВАТЬ: попробуйте что-то вроде этого для заказа:

for x in sorted(l.keys()):
   for y in sorted(l[x].keys()):
       print l[x][y]
3 голосов
/ 30 марта 2009

Вы создаете одномерный список l и хотите использовать его как двумерный список. Вот почему вы получаете ошибку индекса.

У вас есть следующие варианты: создайте карту и используйте кортеж t в качестве индекса:

l = {}
l[t] = something

и вы получите записи в l как:

{(1, 1): something}

если вам нужна традиционная структура массива, я советую вам взглянуть на numpy . С помощью numpy вы получаете n-мерные массивы с «традиционной» индексацией.

Как я уже упоминал, используйте numpy,

с помощью numpy вы можете создать двумерный массив, заполненный нулями или единицами или ... Таким образом, вы можете заполнить любое желаемое значение индексированием [x, y] по своему желанию. Конечно, вы можете перебирать строки и столбцы или весь массив в виде списка.

2 голосов
/ 30 марта 2009

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

>>> x = 3
>>> y = 3
>>> l = [[None] * x for i in range(y)]
>>> l
[[None, None, None], [None, None, None], [None, None, None]]

Что вы можете затем повторить, как вы изначально предложили.

1 голос
/ 30 марта 2009

Что вы подразумеваете именно под "но насколько я знаю словари не могут быть отсортированы по ключам"?

Хотя это не совсем то же самое, что «отсортированный словарь», вы можете легко превратить словарь в список, отсортированный по ключу, который, кажется, соответствует вашему:

>>> tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]
>>> l = {}
>>> for t in tuples:
...    l[t] = "something"
>>> sorted(l) # equivalent to sorted(l.keys())
[(0, 0), (0, 1), (1, 0), (1, 1), (2, 1)]
>>> sorted(l.items()) # make a list of (key, value) tuples, and sort by key
[((0, 0), 'something'), ((0, 1), 'something'), ((1, 0), 'something'), ((1, 1), 'something'), ((2, 1), 'something')]    

(я превратил something в строку "что-то" только для того, чтобы код работал)

Однако, чтобы использовать это в вашем случае (если я правильно понимаю, то есть), вам все равно нужно заполнить словарь значениями None или что-то для каждого «пустого» набора координат)

1 голос
/ 30 марта 2009

Расширение ответа Натана ,

tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]
x = max(tuples, key = lambda z : z[0])[0] + 1
y = max(tuples, key = lambda z : z[1])[1] + 1
l = [[None] * y for i in range(x)]

И тогда ты можешь делать все, что хочешь

0 голосов
/ 30 марта 2009

Приведенные решения, вероятно, лучше всего подходят для большинства целей. Для вашей задачи перебора ключей по порядку, как правило, вместо этого вы должны выполнять итерацию по координатному пространству , а не по ключам dict, точно так же, как это было бы для списка списков. Используйте .get, и вы можете указать значение по умолчанию, которое будет использоваться для пустых ячеек, или, альтернативно, использовать «collections.defaultdict», чтобы определить значение по умолчанию во время создания диктовки. например.

for y in range(10):
    for x in range(10):
        value = mydict.get((x,y), some_default_value)
        # or just "value = mydict[x,y]" if used defaultdict

Если вам нужен фактический список списков, вы можете создать его напрямую, как показано ниже:

max_x, max_y = map(max, zip(*tuples))
l=[[something if (x,y) in tuples else 0 for y in range(max_y+1)] 
     for x in xrange(max_x+1)]

Если список кортежей, вероятно, будет длинным, по соображениям производительности вы можете использовать набор для поиска, так как «(x,y) in tuples» выполняет сканирование списка, а не быстрый поиск по хешу , т.е. измените вторую строку на:

tuple_set = set(tuples)
l=[[something if (x,y) in tuple_set else 0 for y in range(max_y+1)] 
     for x in xrange(max_x+1)]
0 голосов
/ 30 марта 2009

Как упоминалось ранее, вы не можете создавать списки с пробелами, и словари могут быть лучшим выбором здесь. Хитрость заключается в том, чтобы убедиться, что l[t[0]] существует, когда вы помещаете что-то в положение t[1]. Для этого я бы использовал defaultdict .

import collections
tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]
l = collections.defaultdict(dict)
for t in tuples:
    l[t[0]][t[1]] = something

Так как l является дефолтом по умолчанию, если l[t[0]] не существует, он создаст пустой дикт для вас, чтобы поставить something в положение t[1].

Примечание: в конечном итоге это совпадает с ответом @ unwesen, без небольшой утомительной ручной проверки на наличие внутреннего диктата. Поговорите с этим до одновременного ответа.

0 голосов
/ 30 марта 2009

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

Я думаю, что вы объявите это как

l = [][]

Редактировать : синтаксическая ошибка

>>> l = [][]
  File "<stdin>", line 1
    l = [][]
           ^
SyntaxError: invalid syntax
>>> 
...