Список Python - "резервирование" пространства (~ изменение размера)
Мне присваивается список l
, и я хочу выполнить назначение:
l[index] = val
Но может быть случай, когда список слишком мал.
Итак, я хочу, чтобы у меня было место для нового значения.
Иногда мне нужно заполнить новое пространство пустыми строками ''
, а иногда и с другими объектами (например, пустые списки []
, False
или None
).
Для этой задачи я использую следующую процедуру:
def ResizeList(l, size, fill_with=None):
l += [fill_with]*(size-len(l))
(примечание: оно работает, даже если size-len(l)<=0
)
(обратите внимание: поскольку меня интересует резервирование пространства, я намеренно НЕ усекаю его в более короткий список)
Вроде:
ResizeList(l, index+1)
l[index] = val
(При заполнении другим объектом это выглядит как: ResizeList(l, index+1, [])
)
Есть ли еще питонические способы сделать это? Есть ли встроенные или библиотечные функции для этого?
Я использую в основном Python-3.x, но ноу-хау о Python-2x полезно и приветствуется.
Уточнение: Пожалуйста, не говорите мне о dict
, потому что мне нужно list
Для тех, кто хотел бы, чтобы я был более конкретным:
В заявлении о проблеме указывается его тип list
. Использование dict
здесь не является вариантом или решением. Есть причины для этого, особенно связанные с доменом (я делаю прототип эксперимента, который должен показать некоторое асимптотическое поведение, не - как, вероятно, вы привыкли - прототип программы Если это будет "просто прототипом программы", то я согласен с использованием dict и других комментариев). У меня есть следующие предположения:
- У меня много списков (нужно заботиться о производительности и производительности)
- из-за рабочего процесса и необходимости прототипа, я не могу называть расшифрованное C/С++ расширение
- при вычислении окончательный размер списка неизвестен
- мы знаем, что в списке и списки будут плотными
Ячейки списка
- записываются и перезаписываются в неизвестном порядке
Это всего лишь несколько причин, почему я подчеркнул, что мне нужен list
, а не dict
.
Для тех, кто интересуется более подробной информацией или кто хотел бы обсудить dict
, проверку, как мы обсуждаем в комментариях ЗДЕСЬ
Ответы
Ответ 1
Если вы уверены, что список - и не, скажем, dict
- - лучшая структура данных для вашего варианта использования, я предлагаю следующий класс:
class rlist(list):
def __init__(self, default):
self._default = default
def __setitem__(self, key, value):
if key >= len(self):
self += [self._default] * (key - len(self) + 1)
super(rlist, self).__setitem__(key, value)
l = rlist(0)
print(l)
l[10] = 20
print(l)
l[5] = 14
print(l)
Этот класс проверяет, находится ли назначенный индекс, превышает текущую длину списка и автоматически расширяет список по мере необходимости.
Код совместим как с Python 2, так и с 3 (тестируется с 2.6.5 и 3.1.2).
Этот класс может быть полезен, если структура плотная, и вам нужно как можно быстрее найти элемент по индексу. Если структура разрежена, вам следует, вероятно, рассмотреть использование словаря.
Ответ 2
Я придумал что-то, что использует itertool.repeat()
.
import itertools
def assign(lst, idx, value, fill=None):
diff = len(lst) - idx
if diff >= 0:
lst[idx] = value
else:
lst.extend(itertools.repeat(fill, -diff))
lst.append(value)
Это имеет следующее поведение:
>>> l = [0, 1, 2, 3, 4]
>>> assign(l, 2, 'new')
>>> l
[0, 1, 'new', 3, 4]
>>> assign(l, 8, 'new')
>>> l
[0, 1, 'new', 3, 4, None, None, None, 'new']
>>> assign(l, 10, 'new', fill=[])
>>> l
[0, 1, 'new', 3, 4, None, None, None, 'new', [], 'new']
Это работает для вас?
Изменить: С момента обновления вопроса я обновил ответ.
Ответ 3
Возможно, это делает то, что вы хотите:
def resize(l, newsize, filling=None):
if newsize > len(l):
l.extend([filling for x in xrange(len(l), newsize)])
else:
del l[newsize:]
Ответ 4
Попробуйте следующее:
def ResizeList(some_list, length, null_item = None):
return some_list + [null_item
for item in range(length - len(lst))]