首页 > 解决方案 > 不清楚如何解释我的函数中比较字符串寻找差异的特定测试用例

问题描述

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

#abcd

#==^

#abef

这三行的格式是:

1) 完整的第一行。

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

3) 完整的第二行。

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

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

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

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 ""

我遇到的问题是如何解决“如果索引不是可以指示两个输入行的第一个差异的位置的有效索引,该函数还应该返回一个空字符串(再次因为输出不会使否则感觉)。因此,它必须介于 0 和较短线的长度之间。”

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

标签: pythonpython-3.xstringfunctionconditional

解决方案


首先,没有必要将所有特殊条件组合到一个检查中。如果您单独处理这些程序,您的程序将更容易阅读。另外,使用临时变量来避免重复调用函数。对于初学者 ...

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')

我将把申请留作学生的练习。:-)


推荐阅读