Russian Qt Forum

Программирование => Общий => Тема начата: Igors от Февраль 27, 2017, 09:28



Название: Подобные имена
Отправлено: Igors от Февраль 27, 2017, 09:28
Добрый день

Есть объекты имеющие имена (уникальность не гарантируется)
Код:
emo0003-Base:Hips
emo0003-Base:Spine
emo0003-Base:Spine1
... еще 100 таких
Теперь импортируется файл данных где имеются данные с "подобными" имена
Код
C++ (Qt)
emo0003-Straight walking_Loop_Female:Hips
emo0003-Straight walking_Loop_Female:Spine
emo0003-Straight walking_Loop_Female:Spine1
...
 
Необходимо найти какому объекту соответствуют какие данные файла. Подобная задача была, но здесь как исходные так и файловые данные не обязаны все начинаться с какой-то подстроки (префикса). Также нельзя полагаться что "разделитель" всегда двоеточие как в примере выше. Может быть и подчеркивание и знак мейла - как хотят так и именуют.

Понятно что в общем виде задача не определена, нужны доп указания юзера. Сделал банальный find/replace - предъявляю список данных файла и он может подменять. Работает, но вбивать длинные строки руками не хотят, просят "предложить" варианты чтобы можно было выбрать их из комбика. Т.е. для примера выше в диалоге replace должны по умолчанию появляться строки emo0003-Base и emo0003-Straight walking_Loop_Female. Как это сделать?

Спасибо


Название: Re: Подобные имена
Отправлено: deMax от Февраль 27, 2017, 15:42
Из: emo0003-Base:Hips, emo0003-Base:Spine, emo0003-Base:Spine1... найти наибольшую общую подпоследовательность (https://ru.wikipedia.org/wiki/Наибольшая_общая_подпоследовательность) и убрать её
аналогично со вторым списком. Полученные списки должны совпасть.

Если не совпадают и в строках осталась соль(CRC, мусор...) анализировать строки на похожесть, и удалить соль.


Название: Re: Подобные имена
Отправлено: Racheengel от Февраль 27, 2017, 17:50
А нельзя просто сравнивать строки с конца до двоеточия?
Я так понимаю, это и есть разделитель типа Имя:Тип, нет?
Тогда если "типы" совпали - то выдавать их имена в комбик.


Название: Re: Подобные имена
Отправлено: Igors от Февраль 28, 2017, 12:15
Из: emo0003-Base:Hips, emo0003-Base:Spine, emo0003-Base:Spine1... найти наибольшую общую подпоследовательность (https://ru.wikipedia.org/wiki/Наибольшая_общая_подпоследовательность) и убрать её
аналогично со вторым списком. Полученные списки должны совпасть.
"Подпоследовательность" здесь ни при чем, это чисто "подстрока" (см разницу в ссылке) причем стартовая (префикс). А главное - оба набора могут иметь строки не имеющие никакого отношения к префиксам. И как тогда искать - хз. Напр взяли пару строк, у них разные первые буквы, дальше что? 

А нельзя просто сравнивать строки с конца до двоеточия?
Я так понимаю, это и есть разделитель типа Имя:Тип, нет?
Читаем стартовый пост. Я уж не прошу "внимательно", просто читаем
Также нельзя полагаться что "разделитель" всегда двоеточие как в примере выше. Может быть и подчеркивание и знак мейла - как хотят так и именуют.
Пока решил считать разделителем любой символ "не буква и не цифра", не вижу лучшего. Разумеется не гарантируется что базовое имя (напр Hips, Spine) само не имеет того же символа.


Название: Re: Подобные имена
Отправлено: Racheengel от Февраль 28, 2017, 16:27
Пока решил считать разделителем любой символ "не буква и не цифра", не вижу лучшего. Разумеется не гарантируется что базовое имя (напр Hips, Spine) само не имеет того же символа.

а можно считать разделителем символ, который встречается в строке ровно 1 раз?


Название: Re: Подобные имена
Отправлено: Igors от Февраль 28, 2017, 17:13
а можно считать разделителем символ, который встречается в строке ровно 1 раз?
Нет


Название: Re: Подобные имена
Отправлено: Racheengel от Февраль 28, 2017, 17:58
Тогда что чисто визуально можно сказать: матчить с конца до первого несовпадения.
Решение простое, но вряд ли будет лучше других.


Название: Re: Подобные имена
Отправлено: Igors от Март 10, 2017, 14:59
Извиняюсь что исчез - рубанули инет с 1-го (политика)
Тогда что чисто визуально можно сказать: матчить с конца до первого несовпадения.
Решение простое, но вряд ли будет лучше других.
Это только первый шаг: находим "последнее слово" в каждой строке, структурка
Код
C++ (Qt)
typedef QVector<QStringRef> TRefVec;
typedef QPair<TRefVec, TRefVec> TRefPair;   // вектора строк из первого и второго наборов
 
QMap<QString, TRefPair> theMap;
 
Напр для строки с концом "Hips" (ключ) значения будут ссылки на строки из обоих наборов (оба вектора не пустые). Это уже "вариант", т.е. замена приведет к совпадению имен  (хотя бы к одному)

А вот что дальше?


Название: Re: Подобные имена
Отправлено: PinkPanther от Март 11, 2017, 07:12
Хэширование подстрок всех имен (1-й символ имени, 2 первых символа имени, 3 первых символа имени   ...  все символы имени).
При выборе любого объекта, даже если их миллиард, будет легко расставить элементы противоположного массива в порядке максимального соответствия. Полное соответствие - отлично, на символ меньше - хуже, и т.д. Если соответствие достигнуто по длине левого слова, но правые слова длиннее, то чем больше лишних символов справа, тем хуже.
Результаты хранить в словаре (QSet), словарь для каждого массива, индекс - строка, значение - вектор из указателей на объекты или номеров строк в файле.

Пример: xxxxxxx:Linda1, 27 строка в файле
Добавляем 27 в вектор по индексу L
Добавляем 27 в вектор по индексу Li, если индекса нет, создаем...
И так до Linda1.

Отсечь имя можно регулярным выражением "^.+[^a-zA-Z0-9]([a-zA-Z0-9]+)\s*$"


Название: Re: Подобные имена
Отправлено: Igors от Март 17, 2017, 11:13
Пример: xxxxxxx:Linda1, 27 строка в файле
Добавляем 27 в вектор по индексу L
Добавляем 27 в вектор по индексу Li, если индекса нет, создаем...
И так до Linda1.

Отсечь имя можно регулярным выражением "^.+[^a-zA-Z0-9]([a-zA-Z0-9]+)\s*$"
Опять смотрим стартовый пост: конкретный символ-разделитель неизвестен. Уже сейчас неск вариантов: двоеточие, пробел, мейл и подчеркивание. Поэтому полагаем что разделителем может быть любой символ не буква и не цифра


Название: Re: Подобные имена
Отправлено: deMax от Март 24, 2017, 09:43
Есть объекты имеющие имена (уникальность не гарантируется)
В строке "emo0003-Base:Hips" текст "emo0003-Base" и разделитель ":" будут для всех объектов одинаковыми?
Т.е. имя объекта можно получить как QString("text%1text").arg(имя_для_поиска) или возможны случаи: big hips / small spine .


Название: Re: Подобные имена
Отправлено: Igors от Март 24, 2017, 09:58
В строке "emo0003-Base:Hips" текст "emo0003-Base" и разделитель ":" будут для всех объектов одинаковыми?
В рамках данного файла - да. Для другого файла нет, напр другой создатель может юзать
"emo0003-Base@Hips"

Т.е. имя объекта можно получить как QString("text%1text").arg(имя_для_поиска) или возможны случаи: big hips / small spine .
возможны, не гарантируется что разделитель "используется только как разделитель"


Название: Re: Подобные имена
Отправлено: deMax от Март 27, 2017, 12:03
В рамках данного файла - да. Для другого файла нет, напр другой создатель может юзать "emo0003-Base@Hips"
Взять один файл: сравнить первую строку со второй, найти одинаковые начало и конец, а потом эти строки сравнить с третей... получим маску - префикс("emo0003-Base@") + имя("Hips") + суфикс(""). По имени сортировать, или тут что то более хитрое?

В чем сущность разделителя когда текст перед ним всегда одинаковый?


Название: Re: Подобные имена
Отправлено: Igors от Март 27, 2017, 13:06
Взять один файл: сравнить первую строку со второй, найти одинаковые начало ...
Опять читаем первый пост
Подобная задача была, но здесь как исходные так и файловые данные не обязаны все начинаться с какой-то подстроки (префикса). 
... и конец
В одном файле концы строк вряд ли совпадут, ведь это имена объектов без префикса. Но могут быть пары с одинаковыми концами в 2 файлах

Просьба отвечать более вдумчиво, а не так, "лепить лепуху". Спасибо за понимание


Название: Re: Подобные имена
Отправлено: deMax от Март 28, 2017, 10:35
Хотелось бы формализовать задачу, потому что пока не очень понятны входные данные и какие формы они могут принять.
Я правильно понял: есть список объектов, имя состоит из %random_string%separator%name и нам надо найти %separator(который уникален для файла) -> потом находим имя -> поиск? (маску найти тоже легко)
или у нас более общая задача есть 2 списка %random_string%name и найти соответствия элементов?

Может пример приведете самого общего случая? Или правило по которому это имя может сформировано?
так как из этого:
Цитировать
emo0003-Base:Hips
emo0003-Base:Spine
emo0003-Base:Spine1
имя извлечь элементарно


Название: Re: Подобные имена
Отправлено: Igors от Март 28, 2017, 17:06
Пример:

первый список
Цитировать
Some Object   // это "просто имя" (посторонка)
mixamo:Hips    // имя с префиксом
mixamo:Spine    // имя с префиксом
Another Object    // посторонка
mixamo:Spine_Left   // опять имя с префиксом

второй список
Цитировать
prefix1_Hips    // имя с префиксом
Sphere              // посторонка
prefix1_Spine    // имя с префиксом
prefix1_Spine_Left   // опять имя с префиксом
Cube                    // посторонка
...
xyz@Hips    // имена с др префиксом и др разделителем
xyz@Spine   
xyz@Spine_Left   
Сейчас человек видит оба списка в 2 окнах. "Содержательные" имена = Hops, Splne, Spline_Left. Если в первом списке заменить "mixamo:" на "prefix1_" (или "xyz@") - будет совпадение 3 строк в 2 файлах. Вот он и просит: предложите варианты замен, чтобы не вбивать имена руками

Ну и, как уже говорилось, случай общий - вариантов может и вообще не найтись
   


Название: Re: Подобные имена
Отправлено: deMax от Апрель 07, 2017, 11:51
Извиняюсь, давно на форум не заходил. Алгоритм я бы сделал так:
Работа с первым списком для извлечения "mixamo:"
1. Создаем список(сравнивая каждое слово с каждым) начало строки и сколько таких строк: mixamo: - 3 строки, Some - 1 строка...
В процессе создания используем фильтрацию:
- Возможно не стоит учитывать строки если их только 1. (хотя это не универсально)
- Смотрим чтобы строка заканчивалась не на букву, строки "maximo: a" укоротить чтобы оканчивались не буквой.
- обработать строку регуляркой(чтобы хотя бы одна строка или все? соответствовали некоторому формату например"\буквы\символ\буквы"). Возможно удалить строки в которых слов больше двух, нет одного уникального символа для разделения или слова не из предметной области... по хорошему нужно прогнать алгоритм на множестве файлов и определить какие признаки что строка не подходит.

В конце может получиться "mixamo:" - 100 раз, "Some object." - 50 раз, "help-" - 20 раз... возможно mixamo будет самое большое число раз, но универсальнее для каждого слова извлечь слова, потом найти их во втором файле и возможно они там будут для mixamo встречаться чаще, а для других их не будет(хотя и не факт).

2. по второму списку пройтись аналогично, попробовать отыскать наибольшее совпадение из слов для каждого списка первой и второй группы. Хотя чисто теоретически там может "help-" вылезти на первое место, поэтому предложить разные варианты в combobox, отсортировав по количеству совпадений.


Название: Re: Подобные имена
Отправлено: Igors от Апрель 17, 2017, 13:47
Хмм... ну как-то несколько расплывчато, не все дели ясны. В общем я не нашел ничего хорошего, выходит как-то длинно и сложно. Передумал задачу и сделал так

- предъявляется первый список, имена объектов которых нет во втором рисуются красным

- когда юзер дабл-кликает на красный айтем, ему предъвяляется второй список в котором уже выбрана наиболее подходящая строка (во втором находим строку с максимально длинным общим хвостом)

- юзер выбрал во втором (обычно просто Ок), и тут все становится известно: (общий хвост и начала строк в обоих списках). Проверяем в каких строках такая замена прокатит и предлагаем юзеру заменить все найденные