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


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

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

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

Оффлайн ReNzRv

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

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

Оффлайн Azure

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

Оффлайн ReNzRv

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

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Код: (python) [Выделить]
#!/usr/bin/python3

import sys

def diff_weight(pattern, line, weight):
    source = list(line)
    count = 0
    for s in pattern:
        try:
            source.remove(s)
        except ValueError:
            count += 1
            if count > weight:
                return False
    if len(source) + count > weight:
        return False
    return True

weight = int(sys.argv[1])
try:
    with open(sys.argv[2]) as file:
        lines = file.readlines()
except IndexError:
    lines = sys.stdin.readlines()

while lines:
    pattern = lines.pop()
    print(pattern, end="")
    for i in range(len(lines)-1, -1, -1):
        if diff_weight(pattern, lines[i], weight):
            print(lines[i], end="")
            lines.pop(i)
« Последнее редактирование: 20 Июля 2016, 21:13:06 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн Azure

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

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
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

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

Оффлайн ReNzRv

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

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #8 : 20 Июля 2016, 21:26:34 »
В Вашем файле при №=5 получается 3 группы
Код: (html5) [Выделить]












Код:

=====================================================
"A-F2" - показать диалоговое окно панели "Выполнить программу";
"W-r" - показать диалоговое окно панели "Выполнить программу";
=====================================================
"W-F4" - переключиться на рабочее место 4;
"W-F3" - переключиться на рабочее место 3;
"W-F2" - переключиться на рабочее место 2;
"W-F1" - переключиться на рабочее место 1;
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ReNzRv

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

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

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #10 : 20 Июля 2016, 21:48:01 »
Пропускает пустые строки и выводит только подобные
Код: (python) [Выделить]
#!/usr/bin/python3

import sys

def diff_weight(pattern, line, weight):
    source = list(line)
    if len(pattern) > len(line):
        count = 0
    else:
        count = len(line) - len(pattern)
    for s in pattern:
        try:
            source.remove(s)
        except ValueError:
            count += 1
            if count > weight:
                return False
    return True
 
groups=[]
weight = int(sys.argv[1])
try:
    with open(sys.argv[2]) as file:
        lines = file.readlines()
except IndexError:
    lines = sys.stdin.readlines()
 
lines = list(filter("\n".__ne__, lines))
while lines:
    pattern = lines.pop()
    group = pattern
    for i in range(len(lines)-1, -1, -1):
        if diff_weight(pattern, lines[i], weight):
            group += lines[i]
            lines.pop(i)
    if group != pattern:
        groups.append(group)
print(*groups, sep="========\n", end="")

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

Оффлайн ReNzRv

  • Автор темы
  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
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

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

Оффлайн ReNzRv

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


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

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Re: Как найти похожие строки
« Ответ #14 : 21 Июля 2016, 08:43:13 »
Добавил пару проверок
Код: (python) [Выделить]
#!/usr/bin/python3

import sys

def diff_weight(pattern, line, weight):
    source = list(line)
    if len(pattern) >= len(line):
        count = 0
    else:
        count = len(line) - len(pattern)
    for s in pattern:
        try:
            source.remove(s)
        except ValueError:
            count += 1
            if count > weight:
                return False
    return True
 
groups=[]

try:
    weight = int(sys.argv[1])
except (IndexError, ValueError):
    print("ERROR: The decimal next to script.name should indicate max difference")
    exit(1)

try:
    with open(sys.argv[2]) as file:
        lines = file.readlines()
except IndexError:
    lines = sys.stdin.readlines()
lines = list(filter("\n".__ne__, lines))
if not lines:
    print("ERROR: There are no input lines")
    exit(2)

while lines:
    pattern = lines.pop()
    group = pattern
    for i in range(len(lines)-1, -1, -1):
        if diff_weight(pattern, lines[i], weight):
            group += lines.pop(i)
    if group != pattern:
        groups.append(group)
print(*groups, sep="========\n", end="")
А вариант для поиска похожих на одну указанную строку будет?
Так он же и есть в виде функции diff_weight, только надо цикл убрать чтоб не все строки проверял, а только 1.
Выводятся дубликаты строк, т.е от н=0 - что не нужно, хотя можно исправить юником.
Тут подумал, может полезнее/лучше будет добавить аргумент N (min)?
Совершенству конца нет. Тестируйте пока.
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

 

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