【问题标题】:merge adjacent number in a list in python在python的列表中合并相邻的数字
【发布时间】:2016-08-03 10:03:05
【问题描述】:

我有一个包含随机整数的列表。 我想遍历这个列表,如果一个数字和后续数字在一个数字步长内,我想将它们连接到一个子列表中。

例如:

input = [1,2,4,6,7,8,10,11]
output = [[1,2],[4],[6,7,8],[10,11]]

输入列表将始终包含按升序排序的正整数。 我尝试了here的一些代码。

initerator = iter(inputList)
outputList = [c + next(initerator, "") for c in initerator]

虽然我可以连接列表中的每两个条目,但我似乎无法在列表理解中添加合适的if

Python 版本 = 3.4

【问题讨论】:

  • 单线:[[x for i, x in grp] for _, grp in itertools.groupby(enumerate(inputList), lambda x: x[1] - x[0])].
  • 谢谢,这看起来不错......而且我有点理解工作原理......但是如果我在每个条目前加上一个字母,所以我有输入 = [ a1,a2,a4,b6,c7,c8,c10,d11],我也想按字符分组,得到 [[a1,a2],[a4],[b6],[c7,c8],[c10 ],[d11]]....我不完全理解“groupby”和“enumerate”方法,这可能就是为什么我不能得到这个...再次感谢

标签: python list python-3.x list-comprehension listiterator


【解决方案1】:

除非你必须有一个单行,你可以使用一个简单的生成器函数,组合元素直到你碰到一个不连续的元素:

def consec(lst):
    it = iter(lst)
    prev = next(it)
    tmp = [prev]
    for ele in it:
        if prev + 1 != ele:
            yield tmp
            tmp = [ele]
        else:
            tmp.append(ele)
        prev = ele
    yield tmp

输出:

In [2]: lst = [1, 2, 4, 6, 7, 8, 10, 11]

In [3]: list(consec(lst))
Out[3]: [[1, 2], [4], [6, 7, 8], [10, 11]]

【讨论】:

    【解决方案2】:

    没有任何导入的最简单版本:

    def mergeAdjNum(l):
        r = [[l[0]]]
        for e in l[1:]:
            if r[-1][-1] == e - 1:
                r[-1].append(e)
            else:
                r.append([e])
        return r
    

    比一个班轮快约 33%。

    这个处理注释中提到的字符前缀分组:

    def groupPrefStr(l):
        pattern = re.compile(r'([a-z]+)([0-9]+)')
        r = [[l[0]]]
        pp, vv = re.match(pattern, l[0]).groups()
        vv = int(vv)
        for e in l[1:]:
            p,v = re.match(pattern, e).groups()
            v = int(v)
            if p == pp and v == vv + 1:
                r[-1].append(e)
            else:
                pp, vv = p, v
                r.append([e])
        return r
    

    这比只有一个数字要慢得多。知道前缀的确切格式(只有一个字符?)可以帮助避免使用 re 模块并加快速度。

    【讨论】:

      【解决方案3】:

      好方法(找到“拆分”索引,然后切片:

      input = [1,2,4,6,7,8,10,11]
      idx = [0] + [i+1 for i,(x,y) in enumerate(zip(input,input[1:])) if x+1!=y] + [len(input)]
      [ input[u:v] for u,v in zip(idx, idx[1:]) ]
      #output:
      [[1, 2], [4], [6, 7, 8], [10, 11]]
      

      使用enumerate()zip()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多