Не ясно, как учесть конкретный контрольный пример в моей функции, которая сравнивает строки в поисках различий - PullRequest
0 голосов
/ 14 мая 2019

Напишите функцию с именем 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

Как сейчас, мой условный довольно длинный.Я не уверен в хорошем способе учета, если индекс больше, чем длина более короткой строки в моем условном выражении.У меня два вопроса.

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

1 Ответ

1 голос
/ 14 мая 2019

Прежде всего, нет необходимости объединять все ваших особых условий в одну проверку.Ваша программа будет намного проще для чтения, если вы будете обрабатывать их отдельно.Также используйте временные переменные, чтобы избежать повторного вызова функций.Для начала ...

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

Я оставлю заявкув качестве упражнения для студента.: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...