当处理大型列表时,使用numpy
可能是一个不错的选择。
算法
- 创建一个与
y+z
一样大的新数组
- 计算
z
值的坐标
- 在
ypos
处将y
值赋给x
- 在
zpos
处将z
值赋给x
复杂度应为O(n)
,其中n
是值的总数。
import numpy as np
def distribute_values(y_list, z_list, y_pos):
y = np.array(y_list)
z = np.array(z_list)
n = y.size + z.size
x = np.empty(n, np.int)
y_indices = np.array(y_pos) - 1
z_indices = np.setdiff1d(np.arange(n), y_indices, assume_unique=True)
x[y_indices] = y
x[z_indices] = z
return x
print(distribute_values([11, 13, 15], [12, 14], [1, 3, 5]))
print(distribute_values([77], [35, 58, 74], [3]))
作为额外的好处,当
ypos
未排序时,它也能正常工作。
print(distribute_values([15, 13, 11], [12, 14], [5, 3, 1]))
# [11 12 13 14 15]
print(distribute_values([15, 11, 13], [12, 14], [5, 1, 3]))
# [11 12 13 14 15]
性能
当 n
设置为 100 万时,这种方法比@tobias_k的答案稍快,并且比@Joe_Iddon的答案快 500 倍。
列表是按照以下方式创建的:
from random import random, randint
N = 1000000
ypos = [i+1 for i in range(N) if random()<0.4]
y = [randint(0, 10000) for _ in ypos]
z = [randint(0, 1000) for _ in range(N - len(y))
以下是使用%timeit和IPython得出的结果:
使用%timeit
和IPython,结果如下:
%timeit eric(y, z, ypos)
131 ms ± 1.54 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit tobias(y, z, ypos)
224 ms ± 977 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit joe(y,z, ypos)
54 s ± 1.48 s per loop (mean ± std. dev. of 7 runs, 1 loop each)