不清楚如何在比较字符串寻找差异的函数中解释特定测试用例

Not Clear How to Account for a Specific Test Case in My Function that Compares Strings Looking for Differences

编写一个名为 singleline_diff_format 的函数,它接受两个单行字符串和第一个差异的索引,并将生成一个格式化字符串,使用户可以清楚地看到两行之间的第一个差异所在的位置.用户可能希望查看线条上下文中的差异所在,而不仅仅是看到数字。您的函数将 return 一个如下所示的三行字符串:

#abcd

#==^

#abef

这三行的格式是:

1) 完整的第一行。

2) 由重复的等号 (“=”) 组成的分隔线,直到第一个差异。 “^”符号表示第一个差值的位置。

3) 完整的第二行。

如果任一行包含换行符或回车 return 字符(“\n”或“\r”),则函数 return 是一个空字符串(因为这些行不是单行并且输出格式对阅读它的人来说没有意义)。

如果索引不是可以指示两个输入行的第一个差异位置的有效索引,该函数还应该 return 一个空字符串(同样因为否则输出将没有意义).因此,它必须介于 0 和较短线的长度之间。请注意,您不需要检查索引是否确实标识了第一个差异的正确位置,因为在调用此函数之前应该已经正确计算了该索引。

我能够编写该函数,并且我使用 if-else 设置来评估索引是否不等于 -1 以及这些行是否包含任何“\r”或“\n”字符。然后我按照上面的说明打印出结果。如果不满足这些情况,那么函数 return 是一个空字符串。

def singleline_diff_format(line1, line2, idx):
    """
    Inputs:
      line1 - first single line string
      line2 - second single line string
      idx   - index at which to indicate difference
    Output:
      Returns a three line formatted string showing the location
      of the first difference between line1 and line2.

      If either input line contains a newline or carriage return,
      then returns an empty string.

      If idx is not a valid index, then returns an empty string.
    """
    if idx != -1 and "\n" not in line1 and "\n" not in line2 and "\r" not in line1 and "\r" not in line2:
        difference = line1 + "\n" + "=" * idx + "^" + "\n" + line2 + "\n"
        return difference  
    else:
        return ""

我 运行 遇到的问题是如何解决 "If the index is not a valid index that could indicate the position of the first difference of the two input lines, the function should also return an empty string (again because the output would not make sense otherwise). It must therefore be between 0 and the length of the shorter line."

print(singleline_diff_format('abcdefg', 'abc', 5)) #should return empty string

相反,我得到这个:

abcdefg

===^

abc

就目前而言,我的 if 条件非常长。如果索引大于我的条件中较短行的长度,我不确定有什么好的方法来解释。我有两个问题。

1) 有没有办法将我当前的条件语句压缩成更优雅的语句?

2) 如何解释索引可能超过较短行的长度的情况?我有一个功能(见下文)可能对此有所帮助。我应该调用它吗?如果是,我该如何在这种情况下调用它?

潜在有用的功能

IDENTICAL = -1

def singleline_diff(line1, line2):
    """
    Inputs:
      line1 - first single line string
      line2 - second single line string
    Output:
      Returns the index where the first difference between
      line1 and line2 occurs.

      Returns IDENTICAL if the two lines are the same.
    """
    if len(line1) > len(line2):
      i = 0 
      for i in range(len(line2)):
        if line1[i] == line2[i]:
          i += 1
        elif line1[i] != line2[i]:
          return i
      return len(line2)
    elif len(line1) < len(line2):
      i = 0
      for i in range(len(line1)):
        if line1[i] == line2[i]:
          i += 1
        elif line1[i] != line2[i]:
          return i
      return len(line1)
    else: #Condition where the lengths of the strings are equal
      i = 0
      for i in range(len(line1)):
        if line1[i] == line2[i]:
          i += 1
        elif line1[i] != line2[i]:
          return i
      return IDENTICAL

首先,没有必要将您的特殊条件全部复合到一张支票中。如果您分别处理它们,您的程序将 更容易阅读。另外,使用临时变量来避免重复调用函数。对于初学者 ...

len1 = len(line1)
len2 = len(line2)
empty = ""

现在,你的问题条件很简单

# Check for invalid index: too long or negative
if idx >= min(line1, line2) or idx < 0:
    return empty

继续......

# Check for return chars
both_line = line1 + line2
nl = '\n'
ret = '\r'
if nl in both_line or ret in both_line:
    return empty

您还可以简化差异检查。 zip 会让你从你的两个字符串中得到很好的字符对; enumerate 将让您遍历 对循环索引。在下面的前两个示例中,较短字符串的范围内没有差异,因此没有输出。

def diff(line1, line2):

    for idx, pair in enumerate(zip(line1, line2)):
        if pair[0] != pair[1]:
            print(idx, pair)

diff("abc", "abc") 
diff("abc", "abcd")
diff("abz", "abc")
diff("abc", "qbc") 

输出:

2 ('z', 'c')
0 ('a', 'q')

我会将应用程序留给学生作为练习。 :-)