#python #python-3.x #list #numpy
#python #python-3.x #Список #numpy
Вопрос:
Учитывая следующий список (или массив numpy):
x = [4, 3, 1, 2]
Я хочу сгенерировать другой список (или массив numpy) с 1 4 3 2 =10 элементов, таких как:
y = [1, 1, 1, 1, 2, 2, 2, 3, 4, 4]
Где y
будут иметь x[i]
последовательные элементы со значением i
.
Другие примеры:
x = [0,3,1]
y = [2,2,2,3]
x = [2,0,2]
y = [1,1,3,3]
x = [1,1,1,1,1]
y = [1,2,3,4,5]
Как это можно сделать эффективно? Большое спасибо.
Комментарии:
1. Добро пожаловать. Было бы здорово, если бы вы могли также включить написанный вами код.
Ответ №1:
Это делает работу:
x = [4,3,1,2]
y = []
for index, num in enumerate(x):
for i in range(num):
y.append(index 1)
print(y)
или, если вы предпочитаете, с пониманием списка в одной строке:
x = [4,3,1,2]
y = [index 1 for index, num in enumerate(x) for i in range(num)]
print(y)
Вывод:
[1, 1, 1, 1, 2, 2, 2, 3, 4, 4]
Комментарии:
1. @Burak Отлично! Если бы вы могли пометить ответ как решатель, было бы здорово
2. @LorenzoZane другим вариантом было бы
enumerate(x, start=1)
3. @LorenzoZane Кстати, я нашел второе решение наиболее экономичным в чистом Python.
numpy
это другая категория (np.repeat
производительность> 20x для большого набора данных).
Ответ №2:
Если вы хотите использовать numpy
:
x = np.array([4, 3, 1, 2])
a = np.arange(1, x.size 1)
np.repeat(a, x)
Вывод:
array([1, 1, 1, 1, 2, 2, 2, 3, 4, 4])
Комментарии:
1. Почему
np.repeat(a, [*x])
вместоnp.repeat(a, x)
?2. @mathfux — Спасибо, это было излишним. По какой-то причине, когда я изначально писал его, этот метод не работал, но теперь все в порядке. Должно быть, я сделал что-то глупое. Отредактировано — спасибо.
Ответ №3:
Излишне сложный способ сделать это заключается в следующем, используя понимание списка и reduce
функцию:
from functools import reduce
def f(ls):
return reduce(lambda x, y: x y, [[i 1]*ls[i] for i in range(len(ls))])
>>> f([0, 3, 1])
[2, 2, 2, 3]
>>> f([2, 0, 2])
[1, 1, 3, 3]
>>> f([1, 1, 1, 1, 1])
[1, 2, 3, 4, 5]
Комментарии:
1. Это блестяще, но это требует производительности. Это в 8 раз медленнее, чем самое быстрое решение на чистом Python.
Ответ №4:
In [52]: alist, reps = [1,2,3,4], [4,3,1,2]
np.repeat
делает ли такое повторение приятным — но это делает вещи массивами (что требует времени):
In [53]: np.repeat(alist,reps)
Out[53]: array([1, 1, 1, 1, 2, 2, 2, 3, 4, 4])
Повтор списка может использоваться с:
In [54]: [[i]*j for i,j in zip([1,2,3,4],[4,3,1,2])]
Out[54]: [[1, 1, 1, 1], [2, 2, 2], [3], [4, 4]]
и списки списков могут быть сглажены с помощью:
In [55]: [k for l in ([i]*j for i,j in zip(alist, reps)) for k in l]
Out[55]: [1, 1, 1, 1, 2, 2, 2, 3, 4, 4]
In [56]: list(itertools.chain(*([i]*j for i,j in zip(alist, reps))))
Out[56]: [1, 1, 1, 1, 2, 2, 2, 3, 4, 4]
Некоторые тайминги:
In [57]: timeit np.repeat(alist,reps)
10.9 µs ± 398 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Если мы начнем с массивов, результат будет намного быстрее:
In [58]: %%timeit a,b = np.array(alist), np.array(reps)
...: np.repeat(a,b)
...:
2.97 µs ± 103 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Но для этого небольшого примера методы list работают быстрее:
In [59]: timeit [k for l in ([i]*j for i,j in zip(alist, reps)) for k in l]
2.33 µs ± 70.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [60]: timeit list(itertools.chain(*([i]*j for i,j in zip(alist, reps))))
2.46 µs ± 76.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Для больших случаев я ожидаю, что [58] раз будут масштабироваться наилучшим образом. Я не уверен насчет других.