2013-03-14 2 views
3

Скажем, у меня есть этот список:Как увеличить размер и пэд, список python?

[1,2,3,4] 

и я хочу:

[1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4] 

Что такое лучший способ сделать это?

Мой текущий метод, чтобы создать новый список:

x = [1,2,3,4] 
y = [[n]*4 for n in x] 

Это дает:

[[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]] 

Который кажется близко, но не сигара ... Может кто-нибудь помочь?

ответ

13
>>> x = [1,2,3,4] 
>>> [n for n in x for _ in range(4)] 
    [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4] 

 

itertools.repeat действительно семантически чище, спасибо, Стивен:

from itertools import repeat 
[repeated for value in x for repeated in repeat(value, 4)] 
+0

Простота этого трудно победить (+1) – NPE

+2

+1. Мне нравится это лучше всего, но если бы я использовал решение itertools, я бы использовал 'itertools.repeat':' [n2 для n в x для n2 в repeat (n, 4)] '. –

+0

Другое решение 'itertools':' list (chain (* izip (* repeat (x, 4)))) ', но теперь мы опускаемся во что-то, что трудно мысленно разобрать. –

0

Легкий способ:

y = [n for n in x*4] 

Это вернет [1, 2, 3, 4, 1, 2, 3, 4, ...].

Чтобы сделать это в порядке, которое вы хотели, вы можете сделать x = sorted(x) или y = sorted([n for n in x*4]).

Это похоже на y = sorted(x*4).

Лучший способ сделать это, как указано @Pavel Anossov:

y = [n for n in x for _ in range(4)] 

Это лучше, потому что он будет работать для любой последовательности, тогда как sorted(x*4) не сохраняет порядок и работает только для первоначально отсортированных списков.

+0

Ну, это применимо только для отсортированных списков. Действительно ли решает это конкретное решение, но не является универсальным и, следовательно, не может использоваться повторно, что делает его довольно бесполезным. – Qwerty

2

Вы можете использовать itertools.chain() или chain.from_iterable() выравниваться список списков (y в вашем случае):

In [23]: lis=[1,2,3,4] 

In [24]: from itertools import chain 

In [31]: y = list(chain(*([n]*4 for n in lis))) 

In [32]: y 
Out[32]: [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4] 

Некоторые сравнения производительности:

In [25]: x=[1,2,3,4]*1000 #can't use more than 1000 due to limited RAM 

In [26]: %timeit list(chain(*([n]*1000 for n in x))) 
1 loops, best of 3: 196 ms per loop 

In [27]: %timeit list(chain.from_iterable(([n]*1000 for n in x))) 
1 loops, best of 3: 177 ms per loop 

In [29]: %timeit [n for n in x for _ in xrange(1000)] 
1 loops, best of 3: 388 ms per loop 

#three more solutions;from @Steven Rumbalski 

In [28]: %timeit [repeated for value in x for repeated in repeat(value,1000)] 
1 loops, best of 3: 344 ms per loop 

In [30]: %timeit list(chain.from_iterable(izip(*repeat(x,1000)))) 
1 loops, best of 3: 204 ms per loop 

In [31]: %timeit list(chain(*izip(*repeat(x,1000)))) 
1 loops, best of 3: 238 ms per loop 
+0

+1 Интересно, как функция 'reduce' сравнивается (как ответ @nvlass)? – atomh33ls

+0

@ atomh33ls 'reduce()' очень медленный по сравнению с этими альтернативами. –

+1

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

1

Вы всегда можете использовать reduce

reduce(lambda x, y: x+y, [[n]*4 for n in x]) 
+0

Я только что нашел это: 'reduce (list .__ add __, y)', который, похоже, тоже работает. – atomh33ls

+1

@ atomh33ls действительно :) list .__ add__ - это то, что вызывается при использовании '+' в списках – nvlass

+2

'operator.add' быстрее, чем лямбда. –

1

Вот как я сделал бы.

x = [1,2,3,4] 
y = x*4 
y.sort() 

Простой и аккуратный.

Смежные вопросы