python在列表中查找正元素的范围
我有一个清单,例如python在列表中查找正元素的范围,python,list,Python,List,我有一个清单,例如 [0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0] 我想找到元素为正的开始和结束位置: [[3,5],[9,12],[16,18]] 在python中实现这一点的最佳方法是什么? (python中的内置函数,如:find、lambda、itemgetter等。)用于解决方案的原始:( 不确定范围是否可以离开阵列的末端 def get_positive_ranges(a): in_range = False
[0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0]
我想找到元素为正的开始和结束位置:
[[3,5],[9,12],[16,18]]
在python中实现这一点的最佳方法是什么?
(python中的内置函数,如:find、lambda、itemgetter等。)用于解决方案的原始
:(
不确定范围是否可以离开阵列的末端
def get_positive_ranges(a):
in_range = False
result = []
for i in range(len(a)):
if not in_range:
if a[i] > 0:
in_range = True
first = i
else: # Inside a range
if a[i] <= 0: # End of range
in_range = False
result.append([first, i - 1])
if in_range: # Tidy
result.append([first, i])
return result
print(get_positive_ranges([0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0]))
print(get_positive_ranges([]))
print(get_positive_ranges([1]))
print(get_positive_ranges([0, 1]))
print(get_positive_ranges([0, 1, 0]))
def获取正量程(a):
范围内=错误
结果=[]
对于范围内的i(len(a)):
如果不在_范围内:
如果[i]>0:
范围内=真
第一个=我
否则:#在范围内
如果一个[i]有效
lst = [0, 0, 0, 12, 34, 86, 0, 0, 0, 95, 20, 1, 6, 0, 0, 0, 11, 24, 67, 0, 0, 0]
n = len(lst)
starting_points = [i for i in range(n) if lst[i] > 0 and (lst[i - 1] == 0 or i == 0)]
end_points = [next((i for i in range(j + 1, n) if lst[i] == 0), n) - 1 for j in starting_points]
print zip(starting_points, end_points)
输出
[(3, 5), (9, 12), (16, 18)]
这是一个numpy解决方案,不确定这是否比简单的for循环好;请参阅内联注释以获取解释
import numpy as np
a = np.array([0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0])
# get indices of non-zero elements in a
nze = a.nonzero()[0]
# check where the differences of these indices are unequal to one; there you have a jump to/from 0
nze_diff = np.where(np.diff(nze) > 1)[0] + 1
# if a starts with 0, add the index 0
if nze_diff[0] != 0:
nze_diff = np.insert(nze_diff, 0, 0)
# store output
res = []
# loop through the indices and add the desired slices
for ix, i in enumerate(nze_diff):
try:
sl = nze[i:nze_diff[ix + 1]]
res.append([sl[0], sl[-1]])
# means we reached the end of nze_diff
except IndexError:
sl = nze[i:]
res.append([sl[0], sl[-1]])
如果为a
运行,则会收到所需的输出:
[[3, 5], [9, 12], [16, 18]]
可能有比这更聪明的解决方案,但这可能会让你开始
如果您想获得整个范围,它可以简化一点:
res2 = []
for ix, i in enumerate(nze_diff):
try:
res2.append(nze[i:nze_diff[ix + 1]])
except IndexError:
res2.append(nze[i:])
然后,res2
将是:
[array([3, 4, 5]), array([ 9, 10, 11, 12]), array([16, 17, 18])]
如果性能是关键,那么您应该使用很长的列表来测试哪种实现最快。无论如何,这是“索引无数组访问”版本,希望能提高速度。如果您喜欢,它使用映射,lambda
,索引(查找)
。当然,它使用而
input = [0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0]
output = []
input2 = list(map(lambda x: x and (1, -1)[x < 0], input)) # mapping by 'math.sign'-like func
start = end = 0
while end < len(input2):
try:
start = input2.index(1, end + 1)
end = input2.index(0, start) - 1
output.append([start, end])
except ValueError:
break
if start >= end:
output.append([start, len(input2) - 1])
print(output) # [[3, 5], [9, 12], [16, 18]]
input=[0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0,0]
输出=[]
input2=list(映射(lambda x:x和(1,-1)[x<0],输入))#通过类似于函数的“数学符号”进行映射
开始=结束=0
当end=结束:
output.append([start,len(input2)-1])
打印(输出)#[[3,5]、[9,12]、[16,18]]
最后,regex
version.)
input=[0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0,0]
input3=str(列表(
映射(lambda i_x:i_x[0]*(i_x[1]和(1,-1)[i_x[1]<0]),枚举(输入))
))
进口稀土
s=re.sub(r'([\[]0[\],])+','',输入3)
s=s.replace(“,”,“],[”)
如果s[-1:]!=']':
s=s[:-2]+']'
s='['+s[2:]
s=re.sub(r'[0-9]+,'','',s)
输出=列表(评估)
打印(输出)#[[3,5]、[9,12]、[16,18]]
这不是一个python问题,更多的是一个算法问题;)您必须告诉我们您尝试了什么Elahew什么阻止您为此编写for
循环?是否也有负值?我想了解python中是否有内置函数来执行此操作。我的列表很长,并且使用了“for loop”时间效率不高!哦哦哦:。非常好!这是最快和最有效的一个。非常感谢@Sangbok Lee!
input = [0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0]
output = []
input2 = list(map(lambda x: x and (1, -1)[x < 0], input)) # mapping by 'math.sign'-like func
start = end = 0
while end < len(input2):
try:
start = input2.index(1, end + 1)
end = input2.index(0, start) - 1
output.append([start, end])
except ValueError:
break
if start >= end:
output.append([start, len(input2) - 1])
print(output) # [[3, 5], [9, 12], [16, 18]]
input = [0,0,0,12,34,86,0,0,0,95,20,1,6,0,0,0,11,24,67,0,0,0]
input3 = str(list(
map(lambda i_x: i_x[0] * (i_x[1] and (1, -1)[i_x[1] < 0]), enumerate(input))
))
import re
s = re.sub(r'([\[ ]0[\],])+', ' ', input3)
s = s.replace(', ', '], [')
if s[-1:] != ']':
s = s[:-2] + ']'
s = '[' + s[2:]
s = re.sub(r' [0-9]+,', '', s)
output = list(eval(s))
print(output) # [[3, 5], [9, 12], [16, 18]]