Python-查找每个元素左侧第一个非零元素的索引

时间:2019-01-24 20:43:20

标签: python algorithm

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

给出诸如row = [1 0 0 1 0 1 0 1]之类的任何行,我要输出显示output = [0 -1 -1 0 -1 3 -1 5]的行

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

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

3 个答案:

答案 0 :(得分: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]

由于需要存储先前的索引,因此很难通过列表理解来实现。

答案 1 :(得分:2)

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

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

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

例如:

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

但是,如果第一个值是零,它将仍然具有值-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

答案 2 :(得分:0)

使用列表理解。

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]