如何在python中从列表中获取零值和非零值的索引范围?
我有一个包含零和非零值的列表。我想在列表中找到元组中的零值和非零值的范围。我正在寻找与pythonic方式包免费解决方案。例如如何在python中从列表中获取零值和非零值的索引范围?,python,list,Python,List,我有一个包含零和非零值的列表。我想在列表中找到元组中的零值和非零值的范围。我正在寻找与pythonic方式包免费解决方案。例如 a = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 11, 12, 12, 12, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 42, 54, 61, 61, 68, 73, 103
a = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 11, 12,
12, 12, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 17,
25, 42, 54, 61, 61, 68, 73, 103, 115, 138, 147, 170, 187,
192, 197, 201, 208, 210, 214, 216, 217, 217, 218, 219, 220, 221,
222, 222, 219, 220, 220, 221, 220, 216, 216, 217, 217, 217, 217,
216, 216, 216, 209, 204, 193, 185, 177, 161, 156, 143, 110, 103,
89, 82, 62, 62, 62, 60, 56, 55, 50, 49, 48, 47, 47,
45, 44, 43, 42, 40, 37, 23, 22, 14, 12, 6, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
6, 6, 6, 7, 7, 7, 13, 29, 31, 32, 33, 41, 42,
43, 43, 44, 44, 44, 44, 44, 60, 70, 71, 72, 88, 95,
104, 105, 111, 124, 125, 131, 145, 157, 169, 174, 186, 190, 190,
191, 192, 192, 193, 193, 193, 194, 198, 201, 202, 203, 202, 203,
203, 203, 203, 203, 203, 197, 195, 186, 177, 171, 154, 153, 148,
141, 140, 135, 132, 120, 108, 94, 86, 78, 73, 60, 53, 46,
46, 45, 44, 43, 37, 35, 29, 26, 19, 11, 0]]
输出:idx=[(0,9),(10101),(102128),…]
import numpy as np
unique, counts = np.unique(a, return_counts=True)
idx = tuple(zip(unique, counts))
我想这对你有用 您可以enumerate()
获取索引,itertools.groupby()
将falsy(0
)和truthy值组合在一起,并使用运算符提取开始和结束索引。itemgetter(0,-1)
:
这是一个没有外部库的答案:
pointer = 0
is_zero = True
result = []
def finder(p, is_z):
while (a[p] == 0) is is_z:
p += 1
if p == len(a):
return p
return p
while pointer < len(a):
tmp = finder(pointer, is_zero)
result.append((pointer, tmp - 1))
pointer = tmp
is_zero = not is_zero
print(result)
pointer=0
_zero=真吗
结果=[]
def查找器(p,is_z):
而(a[p]==0)是z:
p+=1
如果p==len(a):
返回p
返回p
当指针
这里是我的建议,没有外部软件包,简短易懂:
# Compute list "b" by replacing any non-zero value of "a" with 1
b = list(map(int,[i != 0 for i in a]))
#Compute ranges of 0 and ranges of 1
idx = [] # result list of tuples
ind = 0 # index of first element of each range of zeros or non-zeros
for n,i in enumerate(b):
if (n+1 == len(b)) or (b[n] != b[n+1]):
# Here: EITHER it is the last value of the list
# OR a new range starts at index n+1
idx.append((ind,n))
ind = n+1
print(idx)
无需导入(因此无需搜索库文档以了解这些导入的工作方式:-)和注释
# results is the output list, each entry is a list of startindex,stopindex
results = []
# each time round the logical value is remembered in previouslvalue
previouslvalue = None
for i,value in enumerate(a):
# get the logical value (==0/!=0) from value
lvalue = True if value != 0 else False
if previouslvalue is None or lvalue != previouslvalue:
# this is either the first entry, or the lvalue has changed
# either way, append a new entry to results, with the current index as start/finish of the run
results.append([i,i])
else:
# same lvalue as previous, extend the last entry to include this index
results[-1][1] = i
# save the logical value for next time round the loop
previouslvalue = lvalue
print results
输出为:
[[0, 9], [10, 101], [102, 128], [129, 217], [218, 252], [253, 338], [339, 362], [363, 447], [448, 490], [491, 580], [581,581]]
回应关于在结果列表中包含逻辑值的评论,这非常简单:
# results is the output list, each entry is a list of startindex,stopindex
results = []
# each time round the
previouslvalue = None
for i,value in enumerate(a):
# get the logical value (==0/!=0) from value
lvalue = True if value != 0 else False
if previouslvalue is None or lvalue != previouslvalue:
# this is either the first entry, or the lvalue has changed
# either way, append a new entry to results, with the current index as start/finish of the run
# include the logical value in the list of results
results.append([i,i,lvalue])
else:
# same lvalue as previous, extend the last entry to include this index
results[-1][1] = i
# save the logical value for next time round the loop
previouslvalue = lvalue
print results
现在的输出是:
[[0, 9, False], [10, 101, True], [102, 128, False], [129, 217, True], [218, 252, False], [253, 338, True], [339, 362, False], [363, 447, True], [448, 490, False], [491, 580, True], [581, 581, False]]
这似乎与OP的预期输出不匹配。它给出的输出与
集合相同。Counter
。如果短小是唯一的目标,那么这就是一个明显的赢家,但我不知道它是如何工作的,而且作为一个单行程序,(根据定义)没有机会包括注释,向代码审阅者解释它是如何工作的。这是给你的一行,嘿?@barny我确实在上面做了解释,我建议你参考enumerate
、itertools
和operator
的文档,但是如果你有任何具体问题,我很乐意尝试在这里回答:)做得好-简单是一大优势,包括注释做得很好。根据您的第一条注释,我不能用一个替换它,因为值是矩阵水平值的总和。我可能会得到“1”作为一个将改变未来计算含义的求和值。@Zara我的建议不会改变名为a
的原始列表的值。它创建另一个临时列表,我将其命名为b
,以计算元组列表。所以这对你来说应该没问题。@Zara关于你对另一个答案添加零值/非零值的评论,你可以使用idx.append((ind,n,str(b[n]))
而不是idx.append((ind,n))
。还是很简单!你的方法很好。我考虑过类似的逻辑,但我无法在代码中实现它。我是否可以添加具有零值和非零值的索引范围?e、 (0,9,'0'),(10101,'1'),(102128,'0'),…]这很简单,只需更改结果。将([i,i])
附加到结果。附加([i,i,左值])
-参见编辑后的答案
[[0, 9, False], [10, 101, True], [102, 128, False], [129, 217, True], [218, 252, False], [253, 338, True], [339, 362, False], [363, 447, True], [448, 490, False], [491, 580, True], [581, 581, False]]