Python-识别列表中的连续数字组

发布于 2021-02-02 23:20:24

我想识别列表中的连续数字组,以便:

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

返回值:

[(2,5), (12,17), 20]

并且想知道实现此目的的最佳方法是什么(特别是如果Python内置了某些东西)。

编辑:注意,我最初忘记提及个人数字应作为个人数字而不是范围返回。

关注者
0
被浏览
220
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    more_itertools.consecutive_groups 是在4.0版中添加的。

    演示版

    import more_itertools as mit
    
    iterable = [2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20]
    [list(group) for group in mit.consecutive_groups(iterable)]
    # [[2, 3, 4, 5], [12, 13, 14, 15, 16, 17], [20]]
    

    应用此工具,我们将生成一个生成器函数来查找连续数字的范围。

    def find_ranges(iterable):
        """Yield range of consecutive numbers."""
        for group in mit.consecutive_groups(iterable):
            group = list(group)
            if len(group) == 1:
                yield group[0]
            else:
                yield group[0], group[-1]
    
    
    iterable = [2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20]
    list(find_ranges(iterable))
    # [(2, 5), (12, 17), 20]
    

    所述源执行模拟一个经典配方(由@Nadia Alramli所证明)。

    注意:more_itertools是可通过安装的第三方软件包pip install more_itertools。



  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    编辑2:回答OP新要求

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

    输出:

    [xrange(2, 5), xrange(12, 17), 20]
    

    你可以将xrange替换为range或任何其他自定义类。

    Python文档对此有一个非常简洁的配方:

    from operator import itemgetter
    from itertools import groupby
    data = [2, 3, 4, 5, 12, 13, 14, 15, 16, 17]
    for k, g in groupby(enumerate(data), lambda (i,x):i-x):
        print map(itemgetter(1), g)
    

    输出:

    [2, 3, 4, 5]
    [12, 13, 14, 15, 16, 17]
    

    如果要获得完全相同的输出,可以执行以下操作:

    ranges = []
    for k, g in groupby(enumerate(data), lambda (i,x):i-x):
        group = map(itemgetter(1), g)
        ranges.append((group[0], group[-1]))
    

    输出:

    [(2, 5), (12, 17)]
    

    编辑:该示例已在文档中进行了解释,但也许我应该对其进行更多解释:

    解决方案的关键是在一定范围内进行区分,以便连续的数字都出现在同一组中。

    如果数据是:[2, 3, 4, 5, 12, 13, 14, 15, 16, 17] 然后groupby(enumerate(data), lambda (i,x):i-x)就相当于以下内容:

    groupby(
        [(0, 2), (1, 3), (2, 4), (3, 5), (4, 12),
        (5, 13), (6, 14), (7, 15), (8, 16), (9, 17)],
        lambda (i,x):i-x
    )
    

    lambda函数从元素值中减去元素索引。因此,当你在每个项目上应用lambda时。你将获得groupby的以下密钥:

    [-2, -2, -2, -2, -8, -8, -8, -8, -8, -8]
    

    groupby按相等的键值将元素分组,因此前4个元素将被分组在一起,依此类推。

    我希望这使它更具可读性。

    python 3 版本可能对初学者有所帮助

    首先导入所需的库

    from itertools import groupby
    from operator import itemgetter
    
    ranges =[]
    
    for k,g in groupby(enumerate(data),lambda x:x[0]-x[1]):
        group = (map(itemgetter(1),g))
        group = list(map(int,group))
        ranges.append((group[0],group[-1]))
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看