Форум русскоязычного сообщества Ubuntu


Получить помощь и пообщаться с другими пользователями Ubuntu можно
на irc канале #ubuntu-ru в сети Freenode
и в Jabber конференции ubuntu@conference.jabber.ru

Автор Тема: Как найти похожие строки  (Прочитано 1004 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Как найти похожие строки
« : 20 Июль 2016, 00:43:49 »
Из потока строк нужно найти "похожие" строки группами, или похожие на одну указанную.

Похожие - это строки отличающиеся не более чем на N любых символов в любом месте и последовательности. Соответственно должно указыватся только число N символов.
« Последнее редактирование: 20 Июль 2016, 16:23:54 от renzrv »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
из потока строк найти похожие?
Уточните: надо вывести все похожие строки группами или найти похожую на 1 заданную?
Вряд ли задача решается регулярками — надо ведь считать количество совпадений и сравнивать с N (решается с помощью awk и других высокоуровневых языках на раз-два)
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Azure,
Группами, но и поиск похожей на одну указанную тоже очень пригодится) :)

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Код: Python
  1. #!/usr/bin/python3
  2.  
  3. import sys
  4.  
  5. def diff_weight(pattern, line, weight):
  6.     source = list(line)
  7.     count = 0
  8.     for s in pattern:
  9.         try:
  10.             source.remove(s)
  11.         except ValueError:
  12.             count += 1
  13.             if count > weight:
  14.                 return False
  15.     if len(source) + count > weight:
  16.         return False
  17.     return True
  18.  
  19. weight = int(sys.argv[1])
  20. try:
  21.     with open(sys.argv[2]) as file:
  22.         lines = file.readlines()
  23. except IndexError:
  24.     lines = sys.stdin.readlines()
  25.  
  26. while lines:
  27.     pattern = lines.pop()
  28.     print(pattern, end="")
  29.     for i in range(len(lines)-1, -1, -1):
  30.         if diff_weight(pattern, lines[i], weight):
  31.             print(lines[i], end="")
  32.             lines.pop(i)
« Последнее редактирование: 20 Июль 2016, 21:13:06 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #4 : 20 Июль 2016, 20:26:04 »
Вот как важно иметь тестовые данные… Элементарные ошибки сам бы поправил.
Ещё попытка!
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #5 : 20 Июль 2016, 20:30:55 »
./Find_similar_strings.py 5 "test_text.txt">>>
*куски текста*
Traceback (most recent call last):
  File "./Find_similar_strings.py", line 30, in <module>
    if diff_weight(pattern, lines[i], weight):
IndexError: list index out of range
test_text.txt прикрепил.

Пользователь добавил сообщение 20 Июль 2016, 21:00:53:
скрипт должен вывести например эти строки:
(Нажмите, чтобы показать/скрыть)

сортировать строки нужно? или он найдет похожие независимо от расположения в файле/потоке?
« Последнее редактирование: 20 Июль 2016, 21:05:24 от renzrv »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #6 : 20 Июль 2016, 21:16:11 »
Строка «Код:» и пустые — подобные.
Выводить надо только имеющие подобных? Я просто сделал групировку…
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #7 : 20 Июль 2016, 21:25:11 »
Да, все подобные строки группами кроме пустых. Главное чтобы выполнялось условие: "похожие - это строки отличающиеся не более чем на N любых любых символов в любом месте и последовательности"

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #8 : 20 Июль 2016, 21:26:34 »
В Вашем файле при №=5 получается 3 группы
Код: HTML5
  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13. Код:
  14.  
  15. =====================================================
  16. "A-F2" - показать диалоговое окно панели "Выполнить программу";
  17. "W-r" - показать диалоговое окно панели "Выполнить программу";
  18. =====================================================
  19. "W-F4" - переключиться на рабочее место 4;
  20. "W-F3" - переключиться на рабочее место 3;
  21. "W-F2" - переключиться на рабочее место 2;
  22. "W-F1" - переключиться на рабочее место 1;
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #9 : 20 Июль 2016, 21:32:35 »
Почему "Код:" попал в группу? ("код" в файле 1 шт.)

Строки тогда будут фильтроватся через: | sed '/^\s*$/d'
« Последнее редактирование: 20 Июль 2016, 21:48:01 от renzrv »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #10 : 20 Июль 2016, 21:48:01 »
Пропускает пустые строки и выводит только подобные
Код: Python
  1. #!/usr/bin/python3
  2.  
  3. import sys
  4.  
  5. def diff_weight(pattern, line, weight):
  6.     source = list(line)
  7.     if len(pattern) > len(line):
  8.         count = 0
  9.     else:
  10.         count = len(line) - len(pattern)
  11.     for s in pattern:
  12.         try:
  13.             source.remove(s)
  14.         except ValueError:
  15.             count += 1
  16.             if count > weight:
  17.                 return False
  18.     return True
  19.  
  20. groups=[]
  21. weight = int(sys.argv[1])
  22. try:
  23.     with open(sys.argv[2]) as file:
  24.         lines = file.readlines()
  25. except IndexError:
  26.     lines = sys.stdin.readlines()
  27.  
  28. lines = list(filter("\n".__ne__, lines))
  29. while lines:
  30.     pattern = lines.pop()
  31.     group = pattern
  32.     for i in range(len(lines)-1, -1, -1):
  33.         if diff_weight(pattern, lines[i], weight):
  34.             group += lines[i]
  35.             lines.pop(i)
  36.     if group != pattern:
  37.         groups.append(group)
  38. print(*groups, sep="========\n", end="")

Пользователь добавил сообщение 20 Июль 2016, 21:54:18:
Почему "Код:" попал в группу? ("код" в файле 1 шт.)
«Код:» в группе с пустыми строками т.к. == 4 символа, т.е. отличается от пустого на 4 что <5 ;)
« Последнее редактирование: 20 Июль 2016, 23:14:44 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #11 : 20 Июль 2016, 21:56:23 »
Понял, а разделение групп пустой строчкой или "======" можно?
Строки группы:
"W-F4" - переключиться на рабочее место 4;
"W-F3" - переключиться на рабочее место 3;
"W-F2" - переключиться на рабочее место 2;
"W-F1" - переключиться на рабочее место 1;
отличаются друг от друга на 2 символа, но при значении N 3 или 2 вывода нет.
?

Пользователь добавил сообщение 20 Июль 2016, 23:02:54:
Спасибо, уже почти хорошо)
Скопировал 1 строчку в файле, добавил 1 символ, но при н=1 вывода этих строк не получил.
Не принципиально, но добавить бы еще разделитель в начало и конец.
« Последнее редактирование: 20 Июль 2016, 23:02:54 от renzrv »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #12 : 20 Июль 2016, 23:22:18 »
Сделал вроде как.
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 1967
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #13 : 20 Июль 2016, 23:30:59 »
Теперь похоже все верно, спасибо вам, позже буду еще тестить на других примерах строк,
если найду какой баг -напишу.
А вариант для поиска похожих на одну указанную строку будет?


Пользователь добавил сообщение 20 Июль 2016, 23:53:12:
Выводятся дубликаты строк, т.е от н=0 - что не нужно, хотя можно исправить юником.
Тут подумал, может полезнее/лучше будет добавить аргумент N (min)?
« Последнее редактирование: 20 Июль 2016, 23:53:12 от renzrv »

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5659
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #14 : 21 Июль 2016, 08:43:13 »
Добавил пару проверок
Код: Python
  1. #!/usr/bin/python3
  2.  
  3. import sys
  4.  
  5. def diff_weight(pattern, line, weight):
  6.     source = list(line)
  7.     if len(pattern) >= len(line):
  8.         count = 0
  9.     else:
  10.         count = len(line) - len(pattern)
  11.     for s in pattern:
  12.         try:
  13.             source.remove(s)
  14.         except ValueError:
  15.             count += 1
  16.             if count > weight:
  17.                 return False
  18.     return True
  19.  
  20. groups=[]
  21.  
  22. try:
  23.     weight = int(sys.argv[1])
  24. except (IndexError, ValueError):
  25.     print("ERROR: The decimal next to script.name should indicate max difference")
  26.     exit(1)
  27.  
  28. try:
  29.     with open(sys.argv[2]) as file:
  30.         lines = file.readlines()
  31. except IndexError:
  32.     lines = sys.stdin.readlines()
  33. lines = list(filter("\n".__ne__, lines))
  34. if not lines:
  35.     print("ERROR: There are no input lines")
  36.     exit(2)
  37.  
  38. while lines:
  39.     pattern = lines.pop()
  40.     group = pattern
  41.     for i in range(len(lines)-1, -1, -1):
  42.         if diff_weight(pattern, lines[i], weight):
  43.             group += lines.pop(i)
  44.     if group != pattern:
  45.         groups.append(group)
  46. print(*groups, sep="========\n", end="")
А вариант для поиска похожих на одну указанную строку будет?
Так он же и есть в виде функции diff_weight, только надо цикл убрать чтоб не все строки проверял, а только 1.
Выводятся дубликаты строк, т.е от н=0 - что не нужно, хотя можно исправить юником.
Тут подумал, может полезнее/лучше будет добавить аргумент N (min)?
Совершенству конца нет. Тестируйте пока.
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

 

Страница сгенерирована за 0.072 секунд. Запросов: 24.