Как игнорировать строки, используя difflib.ndiff? - PullRequest
2 голосов
/ 08 января 2010

Согласно документации, вы можете предоставить функцию linejunk для игнорирования определенных строк. Тем не менее, я не могу заставить его работать. Вот пример кода для обсуждения:

from re import search
from difflib import ndiff 
t1 = 'one 1\ntwo 2\nthree 3'
t2 = 'one 1\ntwo 29\nthree 3'
diff = ndiff(t1.splitlines(), t2.splitlines(), lambda x: search('2', x))

Я намерен проигнорировать вторую строку, и diff будет генератором, который не показывает никаких отличий.

Спасибо за помощь.

Ответы [ 2 ]

3 голосов
/ 05 июля 2014

Я недавно встречался с той же проблемой.

Вот что я узнал:

ср. http://bugs.python.org/issue14332

Основное назначение * ненужных параметров - ускорить сопоставление с найти различия, а не маскировать различия.

c.f. http://hg.python.org/cpython/rev/0a69b1e8b7fe/

Патч обеспечивает лучшее объяснение понятий "мусор" и "игнорировать" в документах difflib

Эти функции фильтрации нежелательной почты ускоряют сопоставление, чтобы найти различия и не заставляйте игнорировать отличающиеся строки или символы.

0 голосов
/ 09 января 2010

В вашем примере есть проблема: первые два аргумента ndiff должны быть списком строк; у вас есть одна строка, которая обрабатывается как список символов. См. документы . Используйте, например, t1 = 'one 1\ntwo 2\nthree 3'.splitlines()

Однако, как показывает следующий пример, difflib.ndiff не вызывает функцию linejunk для всех строк. Это давнее поведение - проверено с Python 2.2 до 2.6 включительно и 3.1.

Пример сценария:

from difflib import ndiff
t1 = 'one 1\ntwo 2\nthree 3'.splitlines()
t2 = 'one 1\ntwo 29\nthree 3'.splitlines()
def lj(line):
    rval = '2' in line
    print("lj: line=%r, rval=%s" % (line, rval))
    return rval
d = list(ndiff(t1, t2    )); print("%d %r\n" %  (1, d))
d = list(ndiff(t1, t2, lj)); print("%d %r\n" %  (2, d))
d = list(ndiff(t2, t1, lj)); print("%d %r\n" %  (3, d))

Вывод из работы с Python 2.6:

1 ['  one 1', '- two 2', '+ two 29', '?      +\n', '  three 3']

lj: line='one 1', rval=False
lj: line='two 29', rval=True
lj: line='three 3', rval=False
2 ['  one 1', '- two 2', '+ two 29', '?      +\n', '  three 3']

lj: line='one 1', rval=False
lj: line='two 2', rval=True
lj: line='three 3', rval=False
3 ['  one 1', '- two 29', '?      -\n', '+ two 2', '  three 3']

Вы можете сообщить об этом как об ошибке. Однако обратите внимание, что в документах не указано явно, какое значение придается строкам, которые являются «ненужными». Какой выход вы ожидали?

Дальнейшая загадка: добавление этих строк в скрипт:

t3 = 'one 1\n   \ntwo 2\n'.splitlines()
t4 = 'one 1\n\n#\n\ntwo 2\n'.splitlines()
d = list(ndiff(t3, t4      )); print("%d %r\n" %  (4, d))
d = list(ndiff(t4, t3      )); print("%d %r\n" %  (5, d))
d = list(ndiff(t3, t4, None)); print("%d %r\n" %  (6, d))
d = list(ndiff(t4, t3, None)); print("%d %r\n" %  (7, d))

производит этот вывод:

4 ['  one 1', '-    ', '+ ', '+ #', '+ ', '  two 2']

5 ['  one 1', '+    ', '- ', '- #', '- ', '  two 2']

6 ['  one 1', '-    ', '+ ', '+ #', '+ ', '  two 2']

7 ['  one 1', '+    ', '- ', '- #', '- ', '  two 2']

Другими словами, результат при использовании функции linejunk по умолчанию такой же, как и при отсутствии функции linejunk, в случае, когда используются разные «ненужные» строки (пробел за исключением начального хэша).

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

Изменить после получения дополнительной информации

Если ваше намерение состоит в том, чтобы игнорировать все строки, содержащие '2', то есть делать вид, что они не существуют для каких-либо других целей, все, что вам нужно сделать, это превратить притворство в реальность:

t1f = [line for line in t1 if '2' not in line]
t2f = [line for line in t2 if '2' not in line]
diff = ndiff(t1f, t2f)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...