With large lists, it might be a good idea to work with numpy
.
Algorithm
- create a new array as large as
y + z
- calculate coordinates for
z
values
- assign
y
values to x
at ypos
- assign
z
values to x
at zpos
The complexity should be O(n)
, with n
being the total number of values.
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]))
# [11 12 13 14 15]
print(distribute_values([77], [35, 58, 74], [3]))
# [35 58 77 74]
As a bonus, it also works fine when ypos
isn't sorted:
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]
Performance
With n
set to 1 million, this approach is a bit faster than @tobias_k's answer and 500 times faster than @Joe_Iddon's answer.
The lists were created this way:
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))
Here are the results with %timeit
and 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)