【问题标题】:Python: Create an array using values and indices of a given arrayPython:使用给定数组的值和索引创建数组
【发布时间】:2020-11-17 10:44:04
【问题描述】:

给定以下列表(或 numpy 数组):

x = [4, 3, 1, 2]

我想生成另一个包含 1+4+3+2=10 个元素的列表(或 numpy 数组),例如:

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]

如何有效地做到这一点?非常感谢。

【问题讨论】:

  • 欢迎。如果您还可以包含您编写的代码,那就太好了。

标签: python python-3.x list numpy


【解决方案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]

【讨论】:

  • @Burak 完美!如果您可以将答案标记为求解器会很棒
  • @LorenzoZane 另一个变种是enumerate(x, start=1)
  • @LorenzoZane 顺便说一句,我发现第二种解决方案在纯 Python 中最经济。 numpy 是一个不同的类别(np.repeat 对于大型数据集的性能 > 20 倍)。
【解决方案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])

【讨论】:

  • 为什么是np.repeat(a, [*x]) 而不是np.repeat(a, x)
  • @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]

【讨论】:

  • 这很棒,但会降低性能。它比纯 Python 中最快的解决方案慢 8 倍。
【解决方案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)

但是对于这个小样本,列表方法更快:

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] 倍的扩展效果最好。其他的我不确定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-27
    • 2023-03-30
    相关资源
    最近更新 更多