识别列表中不同连续数字的组(Identify groups of varying continuous numbers in a list)

编程入门 行业动态 更新时间:2024-10-28 10:35:16
识别列表中不同连续数字的组(Identify groups of varying continuous numbers in a list)

在另一篇SO文章中 ,一位Python用户询问如何对连续数字进行分组,使得任何序列都可以由其开始/结束代表,并且任何散列表将显示为单个项目。 接受的答案出色地适用于连续序列。

我需要能够适应类似的解决方案,但对于可能(并非总是)不同增量的数字序列。 理想情况下,我如何表示,还包括增量(所以他们会知道它是否是每3,4,5,nth)

参考原始问题,用户询问以下输入/输出

[2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20] # input [(2,5), (12,17), 20]

我想要的是以下内容(注意:为了清楚起见,我写了一个元组作为输出,但是使用其step变量优先选择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

它也可以处理以下输入

[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

我知道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])

In this other SO post, a Python user asked how to group continuous numbers such that any sequences could just be represented by its start/end and any stragglers would be displayed as single items. The accepted answer works brilliantly for continuous sequences.

I need to be able to adapt a similar solution but for a sequence of numbers that have potentially (not always) varying increments. Ideally, how I represent that will also include the increment (so they'll know if it was every 3, 4, 5, nth)

Referencing the original question, the user asked for the following input/output

[2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20] # input [(2,5), (12,17), 20]

What I would like is the following (Note: I wrote a tuple as the output for clarity but xrange would be preferred using its step variable):

[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

And it could also handle the following input

[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

I know that xrange() supports a step so it may be possible to even use a variant of the other user's answer. I tried making some edits based on what they wrote in the explanation but I wasn't able to get the result I was looking for.

For anyone that doesn't want to click the original link, the code that was originally posted by Nadia Alramli is:

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])

最满意答案

您可以创建一个迭代器来帮助分组,并尝试从下一个组中取出下一个元素,该组将成为前一组的结尾:

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

它给你:

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)]

当步长为1它不包含在xrange输出中。

You can create an iterator to help grouping and try to pull the next element from the following group which will be the end of the previous group:

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

which give you:

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)]

When the step is 1 it is not included in the xrange output.

更多推荐

本文发布于:2023-07-20 20:41:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1203723.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数字   列表中   Identify   groups   list

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!