Python 如何在没有groupby的情况下运行长度编码

Python 如何在没有groupby的情况下运行长度编码,python,Python,我已按排序顺序输入,例如: L = [5,5,7,7,7,7,9,10,12,14] 我想计算每个数字出现的次数。这将产生以下输出: [2,4,1,1,1,1] 我不需要存储原始值。我也不想使用groupby。这是因为我将运行最能加速简单循环的代码 我可以通过以下方式来实现效率低下: S = set(L) [L.count(item) for item in S] 是否有一个简单的线性时间解决方案,可能只有一个for循环?编写了一个小函数,以便在数据非常大的情况下提高效率 L1 = [1

我已按排序顺序输入,例如:

L = [5,5,7,7,7,7,9,10,12,14] 
我想计算每个数字出现的次数。这将产生以下输出:

[2,4,1,1,1,1]
我不需要存储原始值。我也不想使用groupby。这是因为我将运行最能加速简单循环的代码

我可以通过以下方式来实现效率低下:

S = set(L)
[L.count(item) for item in S]

是否有一个简单的线性时间解决方案,可能只有一个for循环?

编写了一个小函数,以便在数据非常大的情况下提高效率

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

def countr(lst):
    res = []
    count = 1

    for i in range(len(lst) - 1):
        if lst[i] == lst[i + 1]:
            count += 1
        else:
            res.append(count)
            count = 1

    res.append(count)
    return res

countr(L1)
# [4, 2, 1, 1, 1, 1, 1, 7, 1]

countr(L2)
# [4, 2, 1, 1, 1, 1, 1, 8]
这是为以下目的而创建的:

>>> from collections import Counter
>>> counts = Counter([5,5,7,7,7,7,9,10,12,14])
>>> [counts[i] for i in sorted(counts.keys())]
[2, 4, 1, 1, 1, 1]
或者,如果您想优化内存使用,这里有一个函数,它可以接受任何iterable,甚至是从文件中获取数字的生成器:

def run_lengths(lst):
    previous_val = None
    num_vals = 0 
    for i in lst:
        if previous_val is None:
            previous_val = i 
        if i == previous_val:
            num_vals += 1
            continue
        yield num_vals
        previous_val = i 
        num_vals = 1 
    if num_vals:
        yield num_vals

print(list(run_lengths([5,5,7,7,7,7,9,10,12,14])))  # Returns [1, 2, 4, 1, 1, 1]

def file_generator(file_path):
    with open(file_path, 'r') as f:
        for l in f:
            yield int(l.strip())

 print(list(run_lengths(file_generator('my/huge/file.dat'))))

这是不对的。这将计算总发生率,这与项目必须记录的运行长度不同contiguous@CoryKramer输入已排序。您能否确认您确实在查找运行长度计数而不是总计数?换句话说,应该
[1,1,2,2,1,1]
产生
[2,2,2]
[4,2]
?@CoryKramer输入被排序,所以它们是相同的。重写的答案,我猜这有bigO(n)和一个for循环@那更好!将它与使用zip在一对列表上进行迭代而不是索引的解决方案进行速度方面的比较是很有趣的。对于小数据来说,通过执行例如
zip(L,L[1:])
就很容易了,但是对于大数据来说,这不太好,因为它复制了
L
。但是我想你可以用
islice
来完成。不过,这确实需要整个列表都可以保存在内存中。您可以重写
countr
以接受从文件加载的生成器。