Skip to main content
 首页 » 编程设计

python之从 RLE 模式中删除代码重复,而不求助于 Haskell

2025年05月04日10yyy_WW

RLE(运行长度编码)模式似乎在我的工作中出现了很多。

它的本质是,每次您看到“中断”或您到达输入的末尾时,您都会输出自上次“中断”以来遇到的元素的减少。

(在实际的 RLE 中,'break' 只是这个字符与最后一个字符不匹配,但在现实世界中它通常稍微复杂一些,但仍然是当前和最后一个元素的函数。)

我想删除重复的 last_val != None: rle.append((last_val, count)) 条件和 Action ,它们在循环中和结束时都出现。

问题是:

  1. 用函数调用替换它们会产生更多而不是更少的代码。
  2. 保持命令式风格(例如,在 Haskell 中,问题就消失了)。

命令式 Python 代码是:

#!/usr/bin/env python 
 
data = "abbbccac" 
 
if __name__ == '__main__': 
  rle = [] 
  last_val = None 
  count = 0; 
 
  for val in data: 
    if val != last_val and last_val != None: 
      rle.append((last_val, count)) 
      count = 1 
    else: 
      count += 1 
    last_val = val 
  if last_val != None: 
    rle.append((last_val, count)) 
 
  print rle 

附言用函数式语言可以简单地解决:

#!/usr/bin/env runhaskell 
import Data.List (group) 
 
dat = "abbbccac" 
 
rle :: Eq a => [a] -> [(a, Int)] 
rle arr = map (\g -> (head g, length g)) $ group arr 
 
main :: IO () 
main = print $ rle dat 

请您参考如下方法:

使用 Python“包含电池”可以轻松解决:

>>> data = "abbbccac" 
>>> from itertools import groupby 
>>> ilen = lambda gen : sum(1 for x in gen) 
>>> print [(ch, ilen(ich)) for ch,ich in groupby(data)] 
[('a', 1), ('b', 3), ('c', 2), ('a', 1), ('c', 1)] 

groupby 返回 2 元组的迭代器。第一个是表示下一组的值,第二个是可用于迭代组中项目的迭代器。您只需要组的长度,但不能直接获取长度,因此我添加了简单的 ilen lambda 函数来计算迭代器的长度。