Python为每个元素查找左边第一个非零元素的索引

2024-04-20 13:51:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道有很多类似的问题,但这一个明显不同。在

给定任何一行,比如row = [1 0 0 1 0 1 0 1],我想输出一个写着output = [0 -1 -1 0 -1 3 -1 5]的行

基本上这是说,第一个1,指向它自己。第二个1具有索引3,它指向其左侧的1,由于{}的索引为0,所以它是0。第三个1指向它左边的1,它有索引3。最后,第四个1指向它左边的第一个索引5。最后,所有0都设置为-1。在

我能够得到所有1都在使用numpy.nonzero(row)的索引,但我不确定如何在与输入数组相同的维度中分隔这些索引。在


Tags: numpyoutput数组row指向nonzero
3条回答

如果您迭代列表(使用enumerate来跟踪元素索引)并将最后一个索引存储在1(低于任何非零值)的位置(第一次除外),这是相当容易的

row = [1, 0, 0, 1, 0, 1, 0, 1]

prev_index = None

result = []
for i,v in enumerate(row):
    if v:
        result.append(i if prev_index is None else prev_index)
        prev_index = i
    else:
        result.append(-1)

>>> result
[0, -1, -1, 0, -1, 3, -1, 5]

这很难用列表理解来实现,因为需要存储前面的索引。

基本上,我们想要的是将所有0替换为-1,所有非零都替换为前一个0的索引,如果我理解正确的话。

因此,我们可以创建一个与给定数组长度相同的-1的数组,然后用np.where的结果替换一个零视图:

outp = np.full(a.shape, -1)
idxs = a.nonzero()
if len(idxs) > 0:
    outp[idxs] = np.concatenate(([0], idxs[0][:-1]))

例如:

^{pr2}$

但是,如果第一个值是零,它仍将具有值-1,因此索引超出范围,但至少对我来说,不清楚这种情况下应该发生什么。

我们可以写得更优雅一点:

outp = np.full(a.shape, -1)
idxs, = a.nonzero()
if len(idxs) > 0:
    outp[idxs[1:]] = idxs[:-1]
    outp[idxs[0]] = idxs[0]

这允许我们在第一个非零之前填写一个值

outp = np.full(a.shape, -1)
idxs, = a.nonzero()
if len(idxs) > 0:
    outp[idxs[1:]] = idxs[:-1]
    outp[idxs[0]] = idxs[0]
    outp[:idxs[0]] = 0  # or another value before the first non-zero

使用列表理解。

row = [1, 0, 0, 1, 0, 1, 0, 1]
output = [idx-(idx!=0)-list(reversed(row[:max(idx, 1)])).index(1) if i else -1 for idx, i in enumerate(row)]
print(output) # -> [0, -1, -1, 0, -1, 3, -1, 5]

相关问题 更多 >