压缩重复字母列表

时间:2019-01-20 15:03:43

标签: python

在准备考试的同时,我正在解决前几年的考试。

编写函数compress(lst),该函数接收一个非空的重复字母列表,并返回一个元组列表,每个元组都包含字母和数字或后续的重复。 (请参见示例)

例如:

针对:

['a','a', 'b', 'b', 'b', 'c', 'a', 'a']

该函数应返回:

[('a', 2), ('b', 3), ('c', 1), ('a', 2)]

这是我的代码:

def compress(lst):
    res = []
    i = 0
    for letter in lst:
        letter_count = 0
        while i < len(lst) and lst[i] == letter:
            letter_count += 1
            i +=1
        res.append((letter, letter_count))
    return res

我的函数返回:

[('a', 2), ('a', 0), ('b', 3), ('b', 0), ('b', 0), ('c', 1), ('a', 2), ('a', 0)]

我知道为什么会这样做,但是我看不到如何更改我的代码来解决问题。

4 个答案:

答案 0 :(得分:3)

使用itertools模块中的groupby,非常适合这里:

from itertools import groupby

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

print([(k, len(list(v))) for k, v in groupby(lst)])
# [('a', 2), ('b', 3), ('c', 1), ('a', 2)]

答案 1 :(得分:2)

(假设您要更正您的代码)

保存当前分析字母的index,并求和该字母重复多少次,这样就跳过已分析的字母

def compress(lst):
    res = []
    i = 0
    ind = 0
    while ind < len(lst):
        letter_count = 0
        while i < len(lst) and lst[i] == lst[ind]:
            letter_count += 1
            i +=1
        res.append((lst[ind], letter_count))
        ind += letter_count
    return res

>>> compress(['a','a', 'b', 'b', 'b', 'c', 'a', 'a'])
[('a', 2), ('b', 3), ('c', 1), ('a', 2)]

答案 2 :(得分:1)

问题在于while循环正确地计算了发生次数,for循环无情地前进,一次一个字符。由于您已经在while循环中正确地增加了索引,所以最简单的方法是完全摆脱forwhile循环。在这里进行多个循环的唯一目的是尝试避免使用if,并且如您所见,这实际上是行不通的。

res = []
prev = ''
for letter in lst:
    if prev == letter:
        letter_count += 1
    else:
        if prev:
            res.append((prev, letter_count))
        letter_count = 1
    prev = letter

这类似于您从itertools.groupby获得的收益:

[(k, len(list(g))) for k, g in groupby(lst)]

答案 3 :(得分:1)

$ ls file100.txt file10.txt file1.txt file2.txt file3.txt $ rename -n 's/\d+/sprintf("%03d", $&)/e' *.txt rename(file10.txt, file010.txt) rename(file1.txt, file001.txt) rename(file2.txt, file002.txt) rename(file3.txt, file003.txt) 是Python方式。如果您想模拟它,则可以使用groupby来实现,它只有一个循环,没有索引(不是很pythonic),并且有一个变量来存储前一个字母:

O(1)

结果:

def compress(lst):
    res = []
    previous_letter = None
    count = 0

    for letter in lst:
        if previous_letter is None:
            # first time
            count += 1
            previous_letter = letter
        elif previous_letter == letter:
            # same letter as before, count
            count += 1
        else:
            # different letter: store result, reset counter
            res.append((previous_letter,count))
            count = 1
            previous_letter = letter

     # last iteration doesn't append the last result, fix this
    res.append((previous_letter,count))
    return res