Список 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))]