在列表中计算连续数字

5

我找不到一个类似的问题,可以让我开发出令人满意的答案。

我对Python(3.4.3)还比较新。我试图使用for循环将元素添加到输出列表中,通过比较输入列表中的每个元素和它后面的元素。

这是我的代码:

random_list=[1,4,5,6,7,9,19,21,22,23,24]

def count_consec(random_list):
    count=1
    consec_list=[]
    for i in listrand:
        if listrand[i] == listrand[i+1]+1:
            count+=1
        else:
            list.append(count)
    return consec_list

基本上,我想将代表random_list[]中连续数字块长度的值添加到consec_list[]中。
在这种情况下,我希望输出如下所示:
[1,4,1,1,4]

这里有一个单一的数字,后面跟着4个连续的数字,再后面是一个单一的数字,接下来是一个单一的数字,最后是4个连续的数字。

我尝试了很多不同的方法,已经得到了构建列表的函数,但所有元素都是1。


listrand 未定义。 - RomanPerekhrest
欢迎来到StackOverflow。请阅读并遵守帮助文档中的发布指南。这里适用于“最小、完整、可验证的示例”。在您发布MCVE代码并准确描述问题之前,我们无法有效地帮助您。 您提供的代码无法编译。在修复参数名称(从random_list更改为listrand)后,由于错误使用append而失败。这不是一个MCVE。 - Prune
我仍然对输出感到困惑 =( - gold_cy
1
@DmitryPolonskiy,输出由列表中数字之间的关系决定:1:1,然后4、5、6、7是4个连续的数字,所以是4,然后9不与列表中前一个或后一个数字连续,因此是“singular”(单数),“19”同样不与列表中其他数字连续:“singular”,因此再加上一个1,然后21、22、23、244个连续的数字:因此为[1, 4, 1, 1, 4]。不用担心,下面的答案会更清晰明了。 :) - chickity china chinese chicken
@downshift 我现在明白了,感谢你的清晰解释。 - gold_cy
5个回答

6
你可以采用以下方法:

您可以采取这样的方法:

def countlist(random_list):
    retlist = []
    # Avoid IndexError for  random_list[i+1]
    for i in range(len(random_list) - 1):
        # Check if the next number is consecutive
        if random_list[i] + 1 == random_list[i+1]:
            count += 1
        else:
            # If it is not append the count and restart counting
            retlist.append(count)
            count = 1
    # Since we stopped the loop one early append the last count
    retlist.append(count)
    return retlist

考虑添加一些注释,尤其是在最后的 retlist.append(count)。虽然对你来说很明显,但OP说他是初学者 :) - Ciprian Tomoiagă
谢谢!除了初始赋值:count = 0之外,这个完美地运行了! - Patrick Abeli
在retlist中,我得到了一些正确的值,但有些不正确。Brian的答案count=0对我非常有帮助。 - mb925

3
您的代码存在一些问题,其中包括未定义的变量,或使用列表中的元素作为该元素的索引,同时在最后一个元素处会出现索引错误,并且您从未将最后一次计数添加到结果列表中。
相反,我建议使用zip(lst,lst [1:])方法来迭代列表中成对的元素,并使用consec [-1]访问和修改已经存在于列表中的计数。
def count_consec(lst):
    consec = [1]
    for x, y in zip(lst, lst[1:]):
        if x == y - 1:
            consec[-1] += 1
        else:
            consec.append(1)
    return consec

random_list=[1,4,5,6,7,9,19,21,22,23,24]
print(count_consec(random_list))
# [1, 4, 1, 1, 4]

或者,您可以从每个元素中减去索引。这样,连续的相邻元素最终将变成相同的元素。现在,您只需使用itertools.groupby来分组和计数这些元素。

>>> random_list=[1,4,5,6,7,9,19,21,22,23,24]
>>> [e-i for i, e in enumerate(random_list)]
[1, 3, 3, 3, 3, 4, 13, 14, 14, 14, 14]
>>> [sum(1 for _ in g) for _, g in itertools.groupby(_)]
[1, 4, 1, 1, 4]

优美的解决方案! - ha554an

1

以下是我的版本

假设你有一个数字列表,想要循环遍历并计算连续的数列:

list_of_nums = [4,5,7,8,2,1,3,5,7,6,8,9,9,9,2,2]

你可以这样做:

streak_count = []
counter = 1
for i in range(len(list_of_nums)):
    if i != (len(list_of_nums) - 1):
        diff = list_of_nums[i+1] - list_of_nums[i]
        if diff == 1:
            counter += 1
        else:
            streak_count.append(counter)
            counter = 1
    else:
        streak_count.append(counter)

1
以下代码进行了修正。您之前是在遍历列表本身的元素,而不是您所引用的计数器。
random_list=[1,4,5,6,7,9,19,21,22,23,24]

def count_consec(listrand):
    count=1
    consec_list=[]
    for i in range(len(listrand[:-1])):
        if listrand[i]+1 == listrand[i+1]:
            count+=1
        else:
            consec_list.append(count)
            count=1

    # Account for the last iteration
    consec_list.append(count)     

    return consec_list

print(count_consec(random_list))      

返回这个:
[1, 4, 1, 1, 4]

0

这里有一种更加Pythonic的解决方案:

alist = [1,4,5,6,7,9,19,21,22,23,24]

在进行差分之前,复制列表的第一个元素,并将一个差值大于1的额外元素与列表的最后一个元素添加到列表末尾

alist = np.array([alist[0]] + alist + [alist[-1]+2])

获取列表中相邻元素之间差值大于1的索引

dif1_loc = np.where(np.diff(alist) != 1)[0]
dif1_loc
> [ 0  1  5  6  7 11]

获取位置之间的差异,以获得连续数字模式的长度。
consec_len = np.diff(dif1_loc).values
consec_len
> array([1, 4, 1, 1, 4])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接