如何找到一个列表中数值递增的索引

6

我有一个类似这样的列表:

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

我需要将索引添加到一个列表中,当元素从0变为1时(而不是从1变为0)。

我尝试了以下方法,但它也会在元素从1变为0时注册。

i = 0 
while i != len(mot)-1:
    if mot[i] != mot[i+1]:
        mot_daily_index.append(i)
    i += 1

此外,不过不是很重要的一点,是否有更加简洁的实现方式?

8个回答

15

以下是您可以使用列表推导式完成的方法:

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]
mot_daily_index = [i for i,m in enumerate(mot) if i and m and not mot[i-1]]
print(mot_daily_index)

输出:

[7, 24]

说明:

  • list(enumerate([7,5,9,3]))会返回[(0, 7), (1, 5), (2, 9), (3, 3)],因此在循环中的i for i, m in enumerate中,im在该迭代中的索引。

6
使用带有筛选器的列表推导式来获取索引:
mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

idx = [i for i,v in enumerate(mot) if i and v > mot[i-1]]
print(idx)

输出:

[7, 24]

3
如果 mot 是一个列表,那么这行代码会枚举除第一个元素外的所有元素,并将大于前一个元素的元素的索引和值作为一个元组返回。 - kabanus

5

您可以使用

lst = [0, 0, 0, 1, 1, 1, 0, 1]
#      0  1  2  3  4  5  6  7

for index, (x, y) in enumerate(zip(lst, lst[1:])):
    if x == 0 and y == 1:
        print("Changed from 0 to 1 at", index)

产生的结果是什么

Changed from 0 to 1 at 2
Changed from 0 to 1 at 6

1
如果不是 x 且 y,则更符合 Python 风格。 - Ann Zen
这大概是我也会写的方式!在上面的其他答案中好像缺少了“zip”。 - Mateen Ulhaq

5

以下是使用 itertools.groupby 将列表分组成 0 和 1 的解决方案:

from itertools import groupby

mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

mot_daily_index = []
l = 0
for s, g in groupby(mot):
    if s == 1:
        mot_daily_index.append(l)
    l += len(list(g))

print(mot_daily_index)

输出:

[7, 24]

4
mot = [0,0,0,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0]
mot_daily_index = [] # the required list
for i in range(len(a)-1):
    if a[i]==0 and a[i+1]==1:
        ind.append(i)

当第i个元素和(i+1)个元素不同时,你的代码会添加索引。


2
对于一个3M元素的容器,这个答案比被接受的答案快了67.2倍。可以通过使用numpy将列表转换为numpy.array来实现。他的答案代码是从Find index where elements change value numpy的代码修改而来的。 那个问题想要所有的过渡v[:-1] != v[1:],而不仅仅是这个问题中的小到大的过渡v[:-1] < v[1:]。 通过将数组与自身移位一位进行比较,创建一个布尔数组。使用np.where返回True的索引。 这会找到变化之前的索引,因为数组在比较时被移位了,所以使用+1来得到正确的值。
import numpy as np

v = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]

# convert to array
v = np.array(v)

# create a Boolean array
map_ = v[:-1] < v[1:]

# return the indices
idx = np.where(map_)[0] + 1

print(idx)
[out]:
array([ 7, 24], dtype=int64)

%timeit

# v is 3M elements
v = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0] * 100000

# accepted answer
%timeit [i for i,m in enumerate(v) if i and m and not v[i-1]]
[out]:
336 ms ± 14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# this answer
v = np.array(v)
%timeit np.where(v[:-1] < v[1:])[0] + 1
[out]:
5.03 ms ± 85.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

1
一个使用zip的一行代码:
mot = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0]

[i+1 for i,m in enumerate(zip(mot[:-1],mot[1:])) if m[0]<m[1]]

# [7, 24]

1
另一种列表推导式写法:
mot = [0,1,1,1,1,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0]

change_mot = [index+1 for index, value in enumerate(zip(mot[:-1], mot[1:], )) if value[1] - value[0] == 1]

Which yields

[1, 8, 11, 15]

这段代码会在增量为1的情况下记录索引。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接