【问题标题】:Avoiding Python Off-by-One Error in RLE Algorithm避免 RLE 算法中的 Python 错误
【发布时间】:2020-02-29 23:04:15
【问题描述】:

编辑:这似乎不仅仅是一个错误的错误。

我在以下简单算法中遇到了一个错误,该算法应该显示字符串中的字母计数,沿着run-length encoding 的行。

我可以看到为什么最后一个字符没有添加到结果字符串中,但是如果我增加irange,我会得到index out of range,原因很明显。

我想从算法设计的角度了解这里的概念问题,以及让我的代码正常工作。

我是否需要一些特殊情况代码来处理原始字符串中的最后一项?或者将当前字符与previous 字符进行比较可能更有意义,尽管这在算法开始时会造成问题?

这种算法是否有通用方法,将当前元素与前一个/下一个元素进行比较,从而避免索引超出范围的问题?

def encode(text):
    # stores output string
    encoding = ""
    i = 0

    while i < len(text) - 1:
        # count occurrences of character at index i
        count = 1
        while text[i] == text[i + 1]:
            count += 1
            i += 1

        # append current character and its count to the result
        encoding += text[i] + str(count) 
        i += 1

    return encoding

text = "Hello World"
print(encode(text))
# Gives H1e1l2o1 1W1o1r1l1

【问题讨论】:

  • 您对外循环和内循环使用相同的计数器 (pos) - 这是一个非常糟糕的主意,特别是因为外循环是 for in range 循环。如果您改用 while 循环,可能会起作用。
  • 另外,你为什么要在外循环结束时增加pos
  • 因为我把外循环从while改成了for。我现在要编辑...

标签: python algorithm off-by-one


【解决方案1】:

你是对的,如果与前一个字符不同(在你的情况下为d),你应该有while i &lt; len(text) 用于外部循环来处理最后一个字符。

您的算法在全局范围内很好,但在查找最后一个字符的出现时会崩溃。此时,text[i+1] 变为非法。

要解决这个问题,只需在内部循环中添加安全检查:while i+1 &lt; len(text)

def encode(text):
    # stores output string
    encoding = ""
    i = 0

    while i < len(text):
        # count occurrences of character at index i
        count = 1
        # FIX: check that we did not reach the end of the string 
        # while looking for occurences
        while i+1 < len(text) and text[i] == text[i + 1]:
            count += 1
            i += 1

        # append current character and its count to the result
        encoding += text[i] + str(count) 
        i += 1

    return encoding

text = "Hello World"
print(encode(text))
# Gives H1e1l2o1 1W1o1r1l1d1

【讨论】:

  • while i + 1 &lt; len(text) 事后看来如此简单明了。还是很棒的,IMO。
【解决方案2】:

如果你保持你的策略,你必须检查i+1 &lt; len(text)。 这给出了类似的东西:

def encode(text): 
    L = len(text) 
    start = 0 
    encoding = '' 
    while start < L: 
        c = text[start] 
        stop = start + 1 
        while stop < L and text[stop] == c: 
            stop += 1 
        encoding += c + str(stop - start) 
        start = stop 
    return encoding

另一种方法是记住每次运行的开始:

def encode2(text): 
     start = 0 
     encoding = '' 
     for i,c in enumerate(text): 
         if c != text[start]: 
             encoding += text[start] + str(i-start) 
             start = i
     if text:
         encoding += text[start] + str(len(text)-start) 
     return encoding

这允许您仅枚举感觉更 Python 的输入。

【讨论】:

    猜你喜欢
    • 2022-12-04
    • 2013-06-23
    • 1970-01-01
    • 2014-05-22
    • 2012-12-06
    • 2020-08-22
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多