在另一篇SO帖子中,Python用户询问如何对连续数字进行分组,使得任何序列都可以由其开始/结束来表示,并且任何散列图都将显示为单个项目.接受的答案对于连续序列非常有效.
我需要能够适应类似的解决方案,但需要一系列具有潜在(并非总是)变化增量的数字.理想情况下,我如何表示也将包括增量(因此他们将知道它是否每隔3,4,5,n)
引用原始问题,用户要求输入/输出以下内容
[2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20] # input
[(2,5), (12,17), 20]
Run Code Online (Sandbox Code Playgroud)
我想要的是以下内容(注意:为了清晰起见,我编写了一个元组作为输出,但是使用其步长变量优先选择xrange):
[2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20] # input
[(2,5,1), (12,17,1), 20] # note, the last element in the tuple would be the step value
Run Code Online (Sandbox Code Playgroud)
它还可以处理以下输入
[2, 4, 6, 8, 12, 13, 14, 15, 16, 17, 20] # input
[(2,8,2), (12,17,1), 20] # note, the last element in the tuple would be the increment
Run Code Online (Sandbox Code Playgroud)
我知道这xrange()支持一个步骤,所以甚至可以使用其他用户答案的变体.我尝试根据他们在解释中写的内容进行一些编辑,但我无法得到我想要的结果.
对于不想单击原始链接的任何人,Nadia Alramli最初发布的代码是:
ranges = []
for key, group in groupby(enumerate(data), lambda (index, item): index - item):
group = map(itemgetter(1), group)
if len(group) > 1:
ranges.append(xrange(group[0], group[-1]))
else:
ranges.append(group[0])
Run Code Online (Sandbox Code Playgroud)
您可以创建一个迭代器来帮助分组,并尝试从以下组中提取下一个元素,该元素将是上一个组的末尾:
def ranges(lst):
it = iter(lst)
next(it) # move to second element for comparison
grps = groupby(lst, key=lambda x: (x - next(it, -float("inf"))))
for k, v in grps:
i = next(v)
try:
step = next(v) - i # catches single element v or gives us a step
nxt = list(next(grps)[1])
yield xrange(i, nxt.pop(0), step)
# outliers or another group
if nxt:
yield nxt[0] if len(nxt) == 1 else xrange(nxt[0], next(next(grps)[1]), nxt[1] - nxt[0])
except StopIteration:
yield i # no seq
Run Code Online (Sandbox Code Playgroud)
这给你:
In [2]: l1 = [2, 3, 4, 5, 8, 10, 12, 14, 13, 14, 15, 16, 17, 20, 21]
In [3]: l2 = [2, 4, 6, 8, 12, 13, 14, 15, 16, 17, 20]
In [4]: l3 = [13, 14, 15, 16, 17, 18]
In [5]: s1 = [i + 10 for i in xrange(0, 11, 2)]
In [6]: s2 = [30]
In [7]: s3 = [i + 40 for i in xrange(45)]
In [8]: l4 = s1 + s2 + s3
In [9]: l5 = [1, 2, 5, 6, 9, 10]
In [10]: l6 = {1, 2, 3, 5, 6, 9, 10, 13, 19, 21, 22, 23, 24}
In [11]:
In [11]: for l in (l1, l2, l3, l4, l5, l6):
....: print(list(ranges(l)))
....:
[xrange(2, 5), xrange(8, 14, 2), xrange(13, 17), 20, 21]
[xrange(2, 8, 2), xrange(12, 17), 20]
[xrange(13, 18)]
[xrange(10, 20, 2), 30, xrange(40, 84)]
[1, 2, 5, 6, 9, 10]
[xrange(1, 3), 5, 6, 9, 10, 13, 19, xrange(21, 24)]
Run Code Online (Sandbox Code Playgroud)
当步长为 时,1它不包含在 xrange 输出中。
| 归档时间: |
|
| 查看次数: |
337 次 |
| 最近记录: |