Основная проблема с вашим решением заключалась в том, что в вашем решении вы вставляли элементы 2 * 383656 раз в существующий список. Каждый раз, когда все элементы после точки вставки приходилось перемещать.
Таким образом, быстрее создавать новый список.
Если по какой-либо причине вы хотите, чтобы cleanData
оставался тем же старым объектом с новыми данными (возможно, потому что другая функция / объект имеет ссылку на него и должна видеть измененные данные), затем напишите
cleanData[:] = blablabla
вместо
cleanData = blablabla
Я написал следующие два решения (второй быстрее только после того, как ответ был принят)
import functools
import operator
cleanData = functools.reduce(
operator.iconcat,
(list(v) for v in zip(*([iter(cleanData)] * 3), listOfX, listOfY)),
[])
и
import itertools
cleanData = list(itertools.chain.from_iterable(
(v for v in zip(*([iter(cleanData)] * 3), listOfX, listOfY)),
))
Чтобы понять конструкцию zip(*([iter(cleanData)] * 3), listOfX, listOfY)
, вы можете посмотреть , что означает [iter (list)] * 2 in python?
Возможный недостаток моего первого решения (в зависимости от контекста). Использование functools.reduce
и operator.iconcat
создает список без генератора.
Второе решение возвращает список. Если вам нужен генератор, просто удалите list(
и один завершающий )
, и это будет генератор
Второе решение (примерно в 2 раза) быстрее первого.
Тогда Я написал код для сравнения производительности и результатов двух заданных решений и моего:
Не очень большая разница (2,5x), но второе решение кажется немного быстрее, чем первое решение @Błotosmętek и Алена Решение T.
from contextlib import contextmanager
import functools
import itertools
import operator
import time
@contextmanager
def measuretime(comment):
print("=" * 76)
t0 = time.time()
yield comment
print("%s: %5.3fs" % (comment, time.time() - t0))
print("-" * 76 + "\n")
N = 383656
t0 = time.time()
with measuretime("create listOfX"):
listOfX = list(range(N))
with measuretime("create listOfY"):
listOfY = list(range(1000000, 1000000 + N))
print("listOfX", len(listOfX), listOfX[:10])
print("listOfY", len(listOfY), listOfY[:10])
with measuretime("create cleanData"):
origCleanData = functools.reduce(
operator.iconcat,
(["2020-010-1T01:00:00.%06d" % i, "c%d" % i, "%d" %i] for i in range(N)),
[])
print("cleanData", len(origCleanData), origCleanData[:12])
cleanData = list(origCleanData)
with measuretime("funct.reduce operator icat + zip"):
newcd1 = functools.reduce(
operator.iconcat,
(list(v) for v in zip(*([iter(cleanData)] * 3), listOfX, listOfY)),
[])
print("NEW", len(newcd1), newcd1[:3*10])
cleanData = list(origCleanData)
with measuretime("itertools.chain + zip"):
cleanData = list(itertools.chain.from_iterable(
(v for v in zip(*([iter(cleanData)] * 3), listOfX, listOfY)),
))
print("NEW", len(cleanData), cleanData[:3*10])
assert newcd1 == cleanData
cleanData = list(origCleanData)
with measuretime("blotosmetek"):
tmp = []
n = min(len(listOfX), len(listOfY), len(cleanData)//3)
for i in range(n):
tmp.extend(cleanData[3*i : 3*i+3])
tmp.append(listOfX[i])
tmp.append(listOfY[i])
cleanData = tmp
print("NEW", len(cleanData), cleanData[:3*10])
assert newcd1 == cleanData
cleanData = list(origCleanData)
with measuretime("alainT"):
cleanData = [ v for i,x,y in zip(range(0,len(cleanData),3),listOfX,listOfY)
for v in (*cleanData[i:i+3],x,y) ]
print("NEW", len(cleanData), cleanData[:3*10])
assert newcd1 == cleanData
Вывод на моем старом P C выглядит так:
============================================================================
create listOfX: 0.013s
----------------------------------------------------------------------------
============================================================================
create listOfY: 0.013s
----------------------------------------------------------------------------
listOfX 383656 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
listOfY 383656 [1000000, 1000001, 1000002, 1000003, 1000004, 1000005, 1000006, 1000007, 1000008, 1000009]
============================================================================
create cleanData: 0.454s
----------------------------------------------------------------------------
cleanData 1150968 ['2020-010-1T01:00:00.000000', 'c0', '0', '2020-010-1T01:00:00.000001', 'c1', '1', '2020-010-1T01:00:00.000002', 'c2', '2', '2020-010-1T01:00:00.000003', 'c3', '3']
============================================================================
funct.reduce operator icat + zip: 0.240s
----------------------------------------------------------------------------
NEW 1918280 ['2020-010-1T01:00:00.000000', 'c0', '0', 0, 1000000, '2020-010-1T01:00:00.000001', 'c1', '1', 1, 1000001, '2020-010-1T01:00:00.000002', 'c2', '2', 2, 1000002, '2020-010-1T01:00:00.000003', 'c3', '3', 3, 1000003, '2020-010-1T01:00:00.000004', 'c4', '4', 4, 1000004, '2020-010-1T01:00:00.000005', 'c5', '5', 5, 1000005]
============================================================================
itertools.chain + zip: 0.109s
----------------------------------------------------------------------------
NEW 1918280 ['2020-010-1T01:00:00.000000', 'c0', '0', 0, 1000000, '2020-010-1T01:00:00.000001', 'c1', '1', 1, 1000001, '2020-010-1T01:00:00.000002', 'c2', '2', 2, 1000002, '2020-010-1T01:00:00.000003', 'c3', '3', 3, 1000003, '2020-010-1T01:00:00.000004', 'c4', '4', 4, 1000004, '2020-010-1T01:00:00.000005', 'c5', '5', 5, 1000005]
============================================================================
blotosmetek: 0.370s
----------------------------------------------------------------------------
NEW 1918280 ['2020-010-1T01:00:00.000000', 'c0', '0', 0, 1000000, '2020-010-1T01:00:00.000001', 'c1', '1', 1, 1000001, '2020-010-1T01:00:00.000002', 'c2', '2', 2, 1000002, '2020-010-1T01:00:00.000003', 'c3', '3', 3, 1000003, '2020-010-1T01:00:00.000004', 'c4', '4', 4, 1000004, '2020-010-1T01:00:00.000005', 'c5', '5', 5, 1000005]
============================================================================
alainT: 0.258s
----------------------------------------------------------------------------
NEW 1918280 ['2020-010-1T01:00:00.000000', 'c0', '0', 0, 1000000, '2020-010-1T01:00:00.000001', 'c1', '1', 1, 1000001, '2020-010-1T01:00:00.000002', 'c2', '2', 2, 1000002, '2020-010-1T01:00:00.000003', 'c3', '3', 3, 1000003, '2020-010-1T01:00:00.000004', 'c4', '4', 4, 1000004, '2020-010-1T01:00:00.000005', 'c5', '5', 5, 1000005]