我有一个如下所示的列表:
Values = [0,0,1,1,1,1,1,2,2,2,3,3,3,3,3,3,4,4,4,5,5,5,5]
我想根据值获取索引范围。例如,对于值“0”,我想得到:
IndexRange0 = range(0,2) = [0,1]
#the element "0" is taking the positions 0 and 1 of the list "Values"
我希望获得值“1”:
IndexRange1 = range(2,7) = [2,3,4,5,6]
等。 最后,我想得到一个“这些范围列表”,让我们说:
FinalOutput = [IndexRange0, IndexRange1, .... IndexRange5]
我不知道如何在不使用昂贵的循环和糟糕的解决方案的情况下实现这一目标。有什么想法吗?
注意:数字将始终逐渐增加。范围的长度是变量(这次有2个“零”,下次它们可能是5个等)但它的顺序总是逐个增加(有一组0,然后是一组1,然后是一组2等,直到非修复整数 n )。在此先感谢您的帮助。
答案 0 :(得分:1)
我建议使用bisect
或itertools.takewhile
,具体取决于您打算如何使用它。
使用bisect:
import bisect
def index_range(n, lst):
return (bisect.bisect_left(lst, n), bisect.bisect_right(lst, n))
def final_output(rng, lst):
return [index_range(n, lst) for n in rng]
values = [0,0,1,1,1,1,1,2,2,2,3,3,3,3,3,3,4,4,4,5,5,5,5]
print(final_output(range(0,6), values))
给出
[(0, 2), (2, 7), (7, 10), (10, 16), (16, 19), (19, 23)]
答案 1 :(得分:1)
使用itertools.groupby
:
from itertools import groupby
from operator import itemgetter
Values = [0,0,1,1,1,1,1,2,2,2,3,3,3,3,3,3,4,4,4,5,5,5,5]
output = []
for k, g in groupby(enumerate(Values), key=itemgetter(1)):
start = next(g)[0]
for end, _ in g: pass
output.append((start, end+1))
print output
输出:
[(0, 2), (2, 7), (7, 10), (10, 16), (16, 19), (19, 23)]
答案 2 :(得分:1)
由于值总是增加1,所以这是另一种方法,无需明确计算每个值的出现次数:
>>> Values = [0,0,1,1,1,1,1,2,2,2,3,3,3,3,3,3,4,4,4,5,5,5,5]
>>> starts = [Values.index(i) for i in range(Values[-1] + 1)] + [len(Values)]
>>> print starts
[0, 2, 7, 10, 16, 19, 23]
>>> ranges = [range(starts[i], starts[i + 1]) for i in range(len(starts) - 1)]
>>> for r in ranges:
... print r
...
[0, 1]
[2, 3, 4, 5, 6]
[7, 8, 9]
[10, 11, 12, 13, 14, 15]
[16, 17, 18]
[19, 20, 21, 22]
答案 3 :(得分:1)
如果您想知道每个数字的范围,您必须将其保存在列表中以保留对该数字的引用。假设你的列表在这个数字之间存在差距
L=[0,0,0,2,2,2,4,5,6,6,7]
仍然是一个增加的序列,但你不知道第二个范围的值是什么,除非你继续引用该值, 这是一个简单的代码:
prev=L[0]
f_index=0
l_index=-1
info = {}
for index, item in enumerate(L):
if prev != item:
l_index=index-1
info[prev]=(f_index,l_index)
prev=item
f_index=index
info[prev]=(f_index,index)
print info
结果如下:
{0: (0, 2), 2: (3, 5), 4: (6, 6), 5: (7, 7), 6: (8, 9), 7: (10, 10)}
现在您可以将其作为2D列表处理,以达到您需要的范围,即
range(info[number][0],info[number][1])
答案 4 :(得分:0)
read the first value
start a run
until end-of-list
read a value
if differs from current
finish the run
start a new run
else
lengthen the run
finish the run