Python中使用列表推导实现游程编码

7 投票
3 回答
4170 浏览
提问于 2025-04-18 18:46

我有一个比较基础的关于运行长度编码(Run Length Encoding)的问题,这个问题和之前很多已经回答过的内容相比要简单一些。简单来说,我想把这个字符串

string = 'aabccccaaa'

转换成

a2b1c4a3

我想如果能把所有信息整理成一个列表,就像我下面展示的那样,我应该能轻松得到a2b1c4a3这个结果。

test = [['a','a'], ['b'], ['c','c','c','c'], ['a','a','a']]

到目前为止,我写出了以下代码,但我想知道有没有人能帮我弄明白怎么才能生成我上面展示的输出。

def string_compression():
    for i in xrange(len(string)):
        prev_item, current_item = string[i-1], string[i]
        print prev_item, current_item
        if prev_item == current_item:
            <HELP>

如果有人有关于更有效解决这个问题的建议,我非常乐意听取!

3 个回答

1

我是一名Python初学者,这是我为RLE(游程编码)写的代码。

s = 'aabccccaaa'
grouped_d = [(k, len(list(g))) for k, g in groupby(s)]

result = ''
for key, count in grouped_d:
    result += key + str(count)

print(f'result = {result}')

2

可以考虑使用 more_itertools.run_length 这个工具。

演示

import more_itertools as mit


iterable = "aabccccaaa"
list(mit.run_length.encode(iterable))
# [('a', 2), ('b', 1), ('c', 4), ('a', 3)]

代码

"".join(f"{x[0]}{x[1]}" for x in mit.run_length.encode(iterable))  # python 3.6
# 'a2b1c4a3'

"".join(x[0] + str(x[1]) for x in mit.run_length.encode(iterable))
# 'a2b1c4a3'

还有其他的 itertools/函数式风格:

"".join(map(str, it.chain.from_iterable(x for x in mit.run_length.encode(iterable))))
# 'a2b1c4a3'

注意:more_itertools 是一个第三方库,可以通过 pip install more_itertools 来安装。

9

你可以使用 itertools.groupby() 这个工具:

from itertools import groupby

grouped = [list(g) for k, g in groupby(string)]

这样做会把每个字母分组,结果会是一个列表的列表。

你可以一步就把它变成 RLE(游程编码):

rle = ''.join(['{}{}'.format(k, sum(1 for _ in g)) for k, g in groupby(string)])

这里的每个 k 是正在分组的字母,而每个 g 是一个迭代器,它会产生 N 次相同的字母;sum(1 for _ in g) 这个表达式是用最有效的方式来计算这些字母的数量。

演示:

>>> from itertools import groupby
>>> string = 'aabccccaaa'
>>> [list(g) for k, g in groupby(string)]
[['a', 'a'], ['b'], ['c', 'c', 'c', 'c'], ['a', 'a', 'a']]
>>> ''.join(['{}{}'.format(k, sum(1 for _ in g)) for k, g in groupby(string)])
'a2b1c4a3'

撰写回答