Оптимальное решение для расширения списка python путем добавления в начале списка вместо хвоста?

У вас есть

x = ['a', 'b', 'c']
y = [1, 2, 3]

И хотите вставить список y в начале x:

x = [1, 2, 3, a, b, c]

Каково оптимальное решение для этого в Python?

Ответ 1

>>> x = ['a', 'b', 'c']
>>> y = [1, 2, 3]
>>> x = y+x

Это простое решение выполняется в два раза быстрее, чем решение с deque для меньших размеров ввода:

$ cat x1.py 
for i in range(1000000):
    x = ['a', 'b', 'c']
    y = [1, 2, 3]
    x = y+x

$ cat x2.py 
from collections import deque
for i in range(1000000):
    d = deque(['a', 'b', 'c'])
    d.extendleft(reversed([1, 2, 3]))

$ time python x1.py

real    0m1.912s
user    0m1.864s
sys     0m0.040s

$ time python x2.py

real    0m5.368s
user    0m5.316s
sys     0m0.052s

Однако он становится медленнее для больших размеров ввода:

>python -m timeit -s "y = range(100000)" "x = list(xrange(10000000)); y+x"
10 loops, best of 3: 229 msec per loop

>python -m timeit -s "from collections import deque; y = range(100000)" "d = deque(xrange(10000000)); d.extendleft(reversed(y))"
10 loops, best of 3: 178 msec per loop

Ответ 2

Если вы хотите добавить слева, deque намного эффективнее, чем список. Используйте метод extendleft.

>>> from collections import deque
>>> d = deque(['a', 'b', 'c'])
>>> d.extendleft(reversed([1, 2, 3]))
>>> d
deque([1, 2, 3, 'a', 'b', 'c'])

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

Ответ 3

В зависимости от того, что вы делаете с результатом, возможно, вы не хотите создавать список вообще:

new_x = itertools.chain(y, x)

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

for val in new_x:
    blah blah

Ответ 4

x[0:0] = y
  • условно простой
  • характеристики производительности: неизвестно
  • сохраняет id (x)