Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Простая метрика сходства текстовых строк - Мир MS Excel

Старая форма входа
  • Страница 1 из 11
  • 1
  • 2
  • 3
  • 10
  • 11
  • »
Модератор форума: _Boroda_, китин  
Мир MS Excel » Вопросы и решения » Готовые решения » Простая метрика сходства текстовых строк (Нечеткий поиск - варианты решения)
Простая метрика сходства текстовых строк
Формуляр Дата: Воскресенье, 21.08.2011, 22:20 | Сообщение № 1
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Метрика основана на подсчёте числа совпадающих 2-значных последовательностей, реализована в виде UDF.
На листе с примерами та же метрика реализована формулами - для иллюстрации принципов расчёта.
Алгоритм сравнения явно нуждается в оптимизации. Собираюсь переделать его с помощью двоичного дерева.
Может кто подкинет ещё идеи получше ...

Основные свойства метрики:

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

Симметрична - не меняется от перестановки аргументов.
Транзитивна для 100% сходства.
К сообщению приложен файл: TextSim.xls (29.5 Kb)


Excel 2003 EN, 2013 EN
 
Ответить
СообщениеМетрика основана на подсчёте числа совпадающих 2-значных последовательностей, реализована в виде UDF.
На листе с примерами та же метрика реализована формулами - для иллюстрации принципов расчёта.
Алгоритм сравнения явно нуждается в оптимизации. Собираюсь переделать его с помощью двоичного дерева.
Может кто подкинет ещё идеи получше ...

Основные свойства метрики:

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

Симметрична - не меняется от перестановки аргументов.
Транзитивна для 100% сходства.

Автор - Формуляр
Дата добавления - 21.08.2011 в 22:20
Формуляр Дата: Понедельник, 22.08.2011, 11:51 | Сообщение № 2
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Значительно оптимизировал алгоритм расчёта. Без всяких деревьев, пока.
К сообщению приложен файл: SimText.xls (30.0 Kb)


Excel 2003 EN, 2013 EN
 
Ответить
СообщениеЗначительно оптимизировал алгоритм расчёта. Без всяких деревьев, пока.

Автор - Формуляр
Дата добавления - 22.08.2011 в 11:51
Alex_ST Дата: Понедельник, 22.08.2011, 17:21 | Сообщение № 3
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Ну, вот ещё кто-то заинтересовался нечётким поиском.
Посмотрите не топик интеллектуальный ВПР (сопоставление ПОХОЖИХ текстов)
И вообще очень много всякого можно нарыть по фразе "нечёткий поиск".
Тема интересная, алгоритмов много, но до полноценной UDF так нигде и не доведено...



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеНу, вот ещё кто-то заинтересовался нечётким поиском.
Посмотрите не топик интеллектуальный ВПР (сопоставление ПОХОЖИХ текстов)
И вообще очень много всякого можно нарыть по фразе "нечёткий поиск".
Тема интересная, алгоритмов много, но до полноценной UDF так нигде и не доведено...

Автор - Alex_ST
Дата добавления - 22.08.2011 в 17:21
Формуляр Дата: Вторник, 23.08.2011, 15:55 | Сообщение № 4
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
На базе вышеприведённой метрики сделал функцию поиска ближайшей по сходству строки.
Методику работы с пробелами, слегка изменил: вместо дополнения по краям строки теперь их вообще игнорируем в цикле перебора знаков (а заодно - все знаки с кодом < 65 'A'). При этом результаты расчёта через формулы перестали соответствовать UDF, поэтому, формулы убрал.
Ну и оптимизировал ещё кой-чего ...
Для примера взял список тем форума.

Благодаря поверхностному знакомству с материалами, любезно рекомендованными Alex_ST, могу сообщить, что предлагаемая метрика является разновидностью метода Q-грамм.
Увы, для более глубокого погружения в бескрайнюю тему нечёткого сходства текстов не хватает ни ума, ни времени.
Может это и дилетантство, но алгоритм работает, причём работает быстро и с приемлемым качеством.
Единственным заметным минусом в плане качества является высокая чувствительность к типичным длинным суффиксам типа "-ование", но, как я понял, наворченные классические алгоритмы с этой проблемой тоже не очень справляются.
К сообщению приложен файл: 3158161.xls (63.5 Kb)


Excel 2003 EN, 2013 EN
 
Ответить
СообщениеНа базе вышеприведённой метрики сделал функцию поиска ближайшей по сходству строки.
Методику работы с пробелами, слегка изменил: вместо дополнения по краям строки теперь их вообще игнорируем в цикле перебора знаков (а заодно - все знаки с кодом < 65 'A'). При этом результаты расчёта через формулы перестали соответствовать UDF, поэтому, формулы убрал.
Ну и оптимизировал ещё кой-чего ...
Для примера взял список тем форума.

Благодаря поверхностному знакомству с материалами, любезно рекомендованными Alex_ST, могу сообщить, что предлагаемая метрика является разновидностью метода Q-грамм.
Увы, для более глубокого погружения в бескрайнюю тему нечёткого сходства текстов не хватает ни ума, ни времени.
Может это и дилетантство, но алгоритм работает, причём работает быстро и с приемлемым качеством.
Единственным заметным минусом в плане качества является высокая чувствительность к типичным длинным суффиксам типа "-ование", но, как я понял, наворченные классические алгоритмы с этой проблемой тоже не очень справляются.

Автор - Формуляр
Дата добавления - 23.08.2011 в 15:55
Alex_ST Дата: Среда, 24.08.2011, 12:50 | Сообщение № 5
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Формуляр,
1. Я бы не стал на всякий случай так рисково писАть: в одном и том же модуле у вас имеется и процедура Public Function textSimilarity и в процедуре Public Function FindBestMatchTxt переменная с именем textSimilarity
Вполне можно было и "наступить на грабли" biggrin
2. А вы не думали, не удастся ли на основе вашего алгоритма сделать аналог фильтра, но с нечётким поиском?



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Среда, 24.08.2011, 12:50
 
Ответить
СообщениеФормуляр,
1. Я бы не стал на всякий случай так рисково писАть: в одном и том же модуле у вас имеется и процедура Public Function textSimilarity и в процедуре Public Function FindBestMatchTxt переменная с именем textSimilarity
Вполне можно было и "наступить на грабли" biggrin
2. А вы не думали, не удастся ли на основе вашего алгоритма сделать аналог фильтра, но с нечётким поиском?

Автор - Alex_ST
Дата добавления - 24.08.2011 в 12:50
Формуляр Дата: Среда, 24.08.2011, 14:56 | Сообщение № 6
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Alex_ST,
спасибо за дельное замечание.
Что касается 2., то для фильтра, по-хорошему, надо из функции на лист массив как-то возвращать, а таких фокусов я пока не освоил ...
А если по-простому, то достаточно в FindBestMatchTxt() в блок сравнения с лучшим результатом вставить сравнение с заданным порогом и всё, что выше - копировать в какой-нибудь новый Range.
Или того проще: для всего массива сравнения считаем во вспомогательном столбце textSimilarity() с искомой строкой, а дальше фильтруем/сортируем N максимальных показателей обычными средствами - вот вам и нечёткий фильтр. biggrin


Excel 2003 EN, 2013 EN

Сообщение отредактировал Формуляр - Среда, 24.08.2011, 15:23
 
Ответить
СообщениеAlex_ST,
спасибо за дельное замечание.
Что касается 2., то для фильтра, по-хорошему, надо из функции на лист массив как-то возвращать, а таких фокусов я пока не освоил ...
А если по-простому, то достаточно в FindBestMatchTxt() в блок сравнения с лучшим результатом вставить сравнение с заданным порогом и всё, что выше - копировать в какой-нибудь новый Range.
Или того проще: для всего массива сравнения считаем во вспомогательном столбце textSimilarity() с искомой строкой, а дальше фильтруем/сортируем N максимальных показателей обычными средствами - вот вам и нечёткий фильтр. biggrin

Автор - Формуляр
Дата добавления - 24.08.2011 в 14:56
Alex_ST Дата: Среда, 24.08.2011, 16:13 | Сообщение № 7
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Можно быть проще: просто имитировать работу автофильтра, делая у строк не попавших в выборку ячеек либо [vba]
Код
EntireRow.Hidden = False
[/vba] либо [vba]
Код
RowHeight = 0
[/vba]



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Четверг, 25.08.2011, 08:49
 
Ответить
СообщениеМожно быть проще: просто имитировать работу автофильтра, делая у строк не попавших в выборку ячеек либо [vba]
Код
EntireRow.Hidden = False
[/vba] либо [vba]
Код
RowHeight = 0
[/vba]

Автор - Alex_ST
Дата добавления - 24.08.2011 в 16:13
Alex_ST Дата: Четверг, 25.08.2011, 16:00 | Сообщение № 8
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Вот, гляньте в аттаче какой нечёткий фильтр я слепил на досуге из разных источников.
Надо будет ещё с дистанцией Ливенштейна разобраться. А FUZZYMATCH работает очень неплохо.

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

Я не возьмусь sad
Дополировать чьё-то - это пожалуйста. А я сам во всех этих мудрёных метриках и дистанциях так до конца и не разобрался.
К сообщению приложен файл: FUZZY_SEARCHING.zip (51.5 Kb)



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Четверг, 25.08.2011, 16:00
 
Ответить
СообщениеВот, гляньте в аттаче какой нечёткий фильтр я слепил на досуге из разных источников.
Надо будет ещё с дистанцией Ливенштейна разобраться. А FUZZYMATCH работает очень неплохо.

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

Я не возьмусь sad
Дополировать чьё-то - это пожалуйста. А я сам во всех этих мудрёных метриках и дистанциях так до конца и не разобрался.

Автор - Alex_ST
Дата добавления - 25.08.2011 в 16:00
Формуляр Дата: Четверг, 25.08.2011, 17:23 | Сообщение № 9
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Alex_ST,

Quote (Alex_ST)
Надо будет ещё с дистанцией Ливенштейна разобраться.

Ливенштейн, как и прочие расстояния редактирования, в моём случае не подходят - они очень чувствительны к перестановке слов,
а мне нужен поиск близких по смыслу заголовков и те же слова в ином порядке должны давать 100% сходства.

Quote
А FUZZYMATCH работает очень неплохо.

Любопытно. Посмотрим на досуге ..


Excel 2003 EN, 2013 EN
 
Ответить
СообщениеAlex_ST,

Quote (Alex_ST)
Надо будет ещё с дистанцией Ливенштейна разобраться.

Ливенштейн, как и прочие расстояния редактирования, в моём случае не подходят - они очень чувствительны к перестановке слов,
а мне нужен поиск близких по смыслу заголовков и те же слова в ином порядке должны давать 100% сходства.

Quote
А FUZZYMATCH работает очень неплохо.

Любопытно. Посмотрим на досуге ..

Автор - Формуляр
Дата добавления - 25.08.2011 в 17:23
Формуляр Дата: Пятница, 26.08.2011, 10:09 | Сообщение № 10
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Quote (Alex_ST)
Но вообще для целей фильтрации любым из методов нужно поискать решение как сравнивать строки разной длины (примерный поиск достаточно короткого шаблона в длинном стринге).

Это вообще-то другая задача - поиск по ключевым словам. И она подразумевает совсем иные требования к метрике, например - асимметричность. Но в качестве косвенного показателя можно использовать TextSimilarity()*len(longStr)/len(shortStr)

Quote (Alex_ST)
Надо будет ещё с дистанцией Ливенштейна разобраться.

Получить сходство из расстояния (и наоборот) довольно просто: s = 1 / (d+1)
К сообщению приложен файл: FUZZY_SEARCHING.rar (48.2 Kb)


Excel 2003 EN, 2013 EN
 
Ответить
Сообщение
Quote (Alex_ST)
Но вообще для целей фильтрации любым из методов нужно поискать решение как сравнивать строки разной длины (примерный поиск достаточно короткого шаблона в длинном стринге).

Это вообще-то другая задача - поиск по ключевым словам. И она подразумевает совсем иные требования к метрике, например - асимметричность. Но в качестве косвенного показателя можно использовать TextSimilarity()*len(longStr)/len(shortStr)

Quote (Alex_ST)
Надо будет ещё с дистанцией Ливенштейна разобраться.

Получить сходство из расстояния (и наоборот) довольно просто: s = 1 / (d+1)

Автор - Формуляр
Дата добавления - 26.08.2011 в 10:09
Alex_ST Дата: Пятница, 26.08.2011, 12:21 | Сообщение № 11
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Хоть кто-то нашёлся, разбирающийся в лингвистическом анализе!

Эх, довести бы нечёткий фильтр до юзабилити...
Но тогда надо чтобы проводился нечёткий поиск по каждому из слов фразы шаблона в словах фраз фильтруемого массива...
Грубо говоря, сначала оценивается сходство первого слова шаблона с каждым из слов каждой из фраз. Потом - второго, ....
В итоге получаем некую матрицу с количеством строк = кол-ву фраз фильтруемого массива а количество столбцов = кол-ву слов фразы шаблона.
В каждой ячейке матрицы - "похожесть" слова шаблона на слова фразы массива.
Потом по этим данным нужно как-то вычислять общую похожесть каждой из фраз массива на фразу шаблона.
Да... мороки много получается. Я не осилю



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеХоть кто-то нашёлся, разбирающийся в лингвистическом анализе!

Эх, довести бы нечёткий фильтр до юзабилити...
Но тогда надо чтобы проводился нечёткий поиск по каждому из слов фразы шаблона в словах фраз фильтруемого массива...
Грубо говоря, сначала оценивается сходство первого слова шаблона с каждым из слов каждой из фраз. Потом - второго, ....
В итоге получаем некую матрицу с количеством строк = кол-ву фраз фильтруемого массива а количество столбцов = кол-ву слов фразы шаблона.
В каждой ячейке матрицы - "похожесть" слова шаблона на слова фразы массива.
Потом по этим данным нужно как-то вычислять общую похожесть каждой из фраз массива на фразу шаблона.
Да... мороки много получается. Я не осилю

Автор - Alex_ST
Дата добавления - 26.08.2011 в 12:21
Формуляр Дата: Пятница, 26.08.2011, 16:30 | Сообщение № 12
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Alex_ST,
Ну, да. Идея вцелом - неплоха. Только это явно уже не подпадает под понятие "простая метрика". smile

Quote (Alex_ST)
Хоть кто-то нашёлся, разбирающийся в лингвистическом анализе!

Это вы, батенька, загнули! Я в этом полный профан. Влез в эту тему только в силу практической необходимости. И углубляться пока не собираюсь. Хотя, тема любопытная ...


Excel 2003 EN, 2013 EN
 
Ответить
СообщениеAlex_ST,
Ну, да. Идея вцелом - неплоха. Только это явно уже не подпадает под понятие "простая метрика". smile

Quote (Alex_ST)
Хоть кто-то нашёлся, разбирающийся в лингвистическом анализе!

Это вы, батенька, загнули! Я в этом полный профан. Влез в эту тему только в силу практической необходимости. И углубляться пока не собираюсь. Хотя, тема любопытная ...

Автор - Формуляр
Дата добавления - 26.08.2011 в 16:30
Формуляр Дата: Пятница, 26.08.2011, 16:44 | Сообщение № 13
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Ну вот - выжал из производительности алгоритма, что мог.
Привинтил сравнение по дереву двоичной сортировки.
И мониторинг числа несовпадающих символов на превышение предела, выше которого текущий максимум теоретически уже недостижим.
Ещё добавил ограничение min уровня сходства, что тоже может сильно ускорить процесс.
К сообщению приложен файл: 5478761.xls (63.5 Kb)


Excel 2003 EN, 2013 EN
 
Ответить
СообщениеНу вот - выжал из производительности алгоритма, что мог.
Привинтил сравнение по дереву двоичной сортировки.
И мониторинг числа несовпадающих символов на превышение предела, выше которого текущий максимум теоретически уже недостижим.
Ещё добавил ограничение min уровня сходства, что тоже может сильно ускорить процесс.

Автор - Формуляр
Дата добавления - 26.08.2011 в 16:44
Alex_ST Дата: Понедельник, 29.08.2011, 17:27 | Сообщение № 14
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Вообще-то очень шустренько работает...
Код бы малость причесать.
А то там сразу после отладки такие перлы остались типа:
[vba]
Код
 If "A" > Mid$(text2, i + 1, 1) Then
        ElseIf "A" > Mid$(text2, i, 1) Then
[/vba]
т.е. первое условие вообще ни к чему не приводит smile
Но даже без этого достаточно компактно, точно и шустро.



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеВообще-то очень шустренько работает...
Код бы малость причесать.
А то там сразу после отладки такие перлы остались типа:
[vba]
Код
 If "A" > Mid$(text2, i + 1, 1) Then
        ElseIf "A" > Mid$(text2, i, 1) Then
[/vba]
т.е. первое условие вообще ни к чему не приводит smile
Но даже без этого достаточно компактно, точно и шустро.

Автор - Alex_ST
Дата добавления - 29.08.2011 в 17:27
Формуляр Дата: Понедельник, 29.08.2011, 18:19 | Сообщение № 15
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Цитата (Alex_ST)
[vba]
Код
If "A" > Mid$(text2, i + 1, 1) Then
ElseIf "A" > Mid$(text2, i, 1) Then
[/vba]
т.е. первое условие вообще ни к чему не приводит


Ну, это не совсем так. Вырывание команд из контекста часто ведёт к неверным выводам ...
[vba]
Код
For i = Len(text1) To 1 Step -1
            If "A" > Mid$(text1, i + 1, 1) Then
            ElseIf "A" > Mid$(text1, i, 1) Then
                i = i - 1
            Else
                sumMax = sumMax + 1
                sumMatch = sumMatch + profile(i)
            End If
        Next i
[/vba]
Этот цикл считает число диад, содержащих только буквенные символы.
Эти 2 условия эквивалентны условию
[vba]
Код
If "A" > Mid$(text1, i + 1, 1) Or "A" > Mid$(text1, i, 1) Then 'пропуск текущей диады
[/vba]

Но есть у меня подозрение, что VBA всегда вычисляет обе части OR, даже если первая даёт TRUE, поэтому решено было оптимизировать проверку в явном виде, разбив на 2 части.
Первое условие необходимо для проверки небуквенного символа в конце строки, а заодно (раз уж от него не избавиться) позволяет прыгать через 2 символа, когда срабатывает 2ое условие.
Другое дело, что первое условие, действительно, срабатывает довольно редко: например, когда встречаются 2 пробела подряд - и оптимальнее было бы поменять условия местами. В процедуре поиска, для которой быстродействие критичней, я так и сделал. А тут - поленился. smile


Excel 2003 EN, 2013 EN

Сообщение отредактировал Формуляр - Понедельник, 29.08.2011, 18:22
 
Ответить
Сообщение
Цитата (Alex_ST)
[vba]
Код
If "A" > Mid$(text2, i + 1, 1) Then
ElseIf "A" > Mid$(text2, i, 1) Then
[/vba]
т.е. первое условие вообще ни к чему не приводит


Ну, это не совсем так. Вырывание команд из контекста часто ведёт к неверным выводам ...
[vba]
Код
For i = Len(text1) To 1 Step -1
            If "A" > Mid$(text1, i + 1, 1) Then
            ElseIf "A" > Mid$(text1, i, 1) Then
                i = i - 1
            Else
                sumMax = sumMax + 1
                sumMatch = sumMatch + profile(i)
            End If
        Next i
[/vba]
Этот цикл считает число диад, содержащих только буквенные символы.
Эти 2 условия эквивалентны условию
[vba]
Код
If "A" > Mid$(text1, i + 1, 1) Or "A" > Mid$(text1, i, 1) Then 'пропуск текущей диады
[/vba]

Но есть у меня подозрение, что VBA всегда вычисляет обе части OR, даже если первая даёт TRUE, поэтому решено было оптимизировать проверку в явном виде, разбив на 2 части.
Первое условие необходимо для проверки небуквенного символа в конце строки, а заодно (раз уж от него не избавиться) позволяет прыгать через 2 символа, когда срабатывает 2ое условие.
Другое дело, что первое условие, действительно, срабатывает довольно редко: например, когда встречаются 2 пробела подряд - и оптимальнее было бы поменять условия местами. В процедуре поиска, для которой быстродействие критичней, я так и сделал. А тут - поленился. smile

Автор - Формуляр
Дата добавления - 29.08.2011 в 18:19
Формуляр Дата: Понедельник, 29.08.2011, 22:51 | Сообщение № 16
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Должен предупредить, что обнаружился косяк в FindBestMatchTxt(), который пока не удаётся красиво причесать.
Если искомая строка и массив сравнения оказываются на разных листах происходит сбой ф-ции Intersect.
Она используется для исключения искомой ячеки, в том случае, когда она находится в массиве сравнения.
В общем-то, это частный случай. Так что, заплаточное решение - закомментировать в sub FindBestMatchTxt строки:
Цитата
[vba]
Код
If Not (Intersect(lookup_value, lookup_array.Cells(txtNum + 1)) Is Nothing) Then
txtNum = txtNum + 1
End If
[/vba]

А если у кого есть идеи, то милости просим сюда Как проверить ячейки на идентичность?


Excel 2003 EN, 2013 EN

Сообщение отредактировал Формуляр - Понедельник, 29.08.2011, 22:53
 
Ответить
СообщениеДолжен предупредить, что обнаружился косяк в FindBestMatchTxt(), который пока не удаётся красиво причесать.
Если искомая строка и массив сравнения оказываются на разных листах происходит сбой ф-ции Intersect.
Она используется для исключения искомой ячеки, в том случае, когда она находится в массиве сравнения.
В общем-то, это частный случай. Так что, заплаточное решение - закомментировать в sub FindBestMatchTxt строки:
Цитата
[vba]
Код
If Not (Intersect(lookup_value, lookup_array.Cells(txtNum + 1)) Is Nothing) Then
txtNum = txtNum + 1
End If
[/vba]

А если у кого есть идеи, то милости просим сюда Как проверить ячейки на идентичность?

Автор - Формуляр
Дата добавления - 29.08.2011 в 22:51
Alex_ST Дата: Вторник, 30.08.2011, 09:31 | Сообщение № 17
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Формуляр,
я честно признаюсь, что в используемый вами алгоритм не вникал (т.к. его описания я в примерах не нашёл, а разбираться самому по комментариям лень).
Поэтому просто пытаюсь "привинтить" вашу процедуру TextSimilarity к своей имитации автофильтра с нечётким поиском.
А процедура TextSimilarity, повторяю, получилась достаточно шустрая и компактная. Поэтому при обработке не слишком больших массивов (в несколько тысяч строк) её вполне можно использовать как вызываемую любой другой процедурой функцию. Что я и делаю в своём примере.
Конечно, если речь идёт об обработке массивов из десятков-сотен тысяч строк, то имеет смысл "ловить блох" на таком мизерном ускорении процедуры, что дают отказ от вызовов внешних процедур, замена [vba]
Код
If … Or … Then
на
Код
If … Then
ElseIf … Then
[/vba] и т.п.

А FindBestMatchTxt я даже и не смотрел...
Но сразу же (опять же, глубоко не вникая) могу предложить первым же шагом уйти от перебора ячеек диапазона lookup_array к перебору массива. Такой метод ВСЕГДА даёт существенное ускорение.
В общем-то я бы сделал так:
1. Диапазон анализируемых строк одной командой перекинуть в массив
2. Записи массива поочерёдно сравнивать с образцом функцией TextSimilarity.
3. Каждый лучший чем предыдущий по проценту совпадения результат записывать в пару переменных "процент" и "строка". По окончании анализа массива в переменной "строка" будет текст наиболее похожей на образец строки.

Да и вообще: перед анализом хорошо бы провести "чистку" массива - убрать лишние пробелы и, наверное, знаки препинания



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Вторник, 30.08.2011, 09:33
 
Ответить
СообщениеФормуляр,
я честно признаюсь, что в используемый вами алгоритм не вникал (т.к. его описания я в примерах не нашёл, а разбираться самому по комментариям лень).
Поэтому просто пытаюсь "привинтить" вашу процедуру TextSimilarity к своей имитации автофильтра с нечётким поиском.
А процедура TextSimilarity, повторяю, получилась достаточно шустрая и компактная. Поэтому при обработке не слишком больших массивов (в несколько тысяч строк) её вполне можно использовать как вызываемую любой другой процедурой функцию. Что я и делаю в своём примере.
Конечно, если речь идёт об обработке массивов из десятков-сотен тысяч строк, то имеет смысл "ловить блох" на таком мизерном ускорении процедуры, что дают отказ от вызовов внешних процедур, замена [vba]
Код
If … Or … Then
на
Код
If … Then
ElseIf … Then
[/vba] и т.п.

А FindBestMatchTxt я даже и не смотрел...
Но сразу же (опять же, глубоко не вникая) могу предложить первым же шагом уйти от перебора ячеек диапазона lookup_array к перебору массива. Такой метод ВСЕГДА даёт существенное ускорение.
В общем-то я бы сделал так:
1. Диапазон анализируемых строк одной командой перекинуть в массив
2. Записи массива поочерёдно сравнивать с образцом функцией TextSimilarity.
3. Каждый лучший чем предыдущий по проценту совпадения результат записывать в пару переменных "процент" и "строка". По окончании анализа массива в переменной "строка" будет текст наиболее похожей на образец строки.

Да и вообще: перед анализом хорошо бы провести "чистку" массива - убрать лишние пробелы и, наверное, знаки препинания

Автор - Alex_ST
Дата добавления - 30.08.2011 в 09:31
Формуляр Дата: Вторник, 30.08.2011, 10:51 | Сообщение № 18
Группа: Друзья
Ранг: Ветеран
Сообщений: 832
Репутация: 255 ±
Замечаний: 0% ±

Excel 2003, 2013
Alex_ST,
Quote (Alex_ST)
Конечно, если речь идёт об обработке массивов из десятков-сотен тысяч строк, то имеет смысл "ловить блох" на таком мизерном ускорении процедуры

не стану спорить, эфффект - мизерный. Это так - от тяги к перфекционизму.

Quote (Alex_ST)
Да и вообще: перед анализом хорошо бы провести "чистку" массива - убрать лишние пробелы и, наверное, знаки препинания

Боюсь чистка массива займёт не меньше времени, чем само сравнение. smile
FindBestMatchTxt обращается к каждой ячейке диапазона только 1 раз и грузит её текст в промежуточную строку txt. Так что, не уверен. что предварительная загрузка всех ячеек в массив типа Array (если я правильно понял эту мысль) даст заметный эффект.

Quote (Alex_ST)
2. Записи массива поочерёдно сравнивать с образцом функцией TextSimilarity.

В FindBestMatchTxt происходит более сложный предварительный анализ искомого текста, что сильно ускоряет последующие циклы сравнения, и делается это 1 раз. А TextSimilarity будет свою простенькую подготовку выполнять многократно и само сравнение будет выполнять медленнее.

Quote (Alex_ST)
3. Каждый лучший чем предыдущий по проценту совпадения результат записывать в пару переменных "процент" и "строка". По окончании анализа массива в переменной "строка" будет текст наиболее похожей на образец строки.

Так оно и происходит: best - это "процент", вместо "строки" - её порядковый номер txtNum запоминается прямо в возвращаемой переменной.

Было бы очень любопытно, если бы вы провели независимое сравнение производительности поиска через TextSimilarity и через FindBestMatchTxt. А то наворотов я там оптимизирующих навешал, а какой от них реальный эффект - толком неизвестно.


Excel 2003 EN, 2013 EN

Сообщение отредактировал Формуляр - Вторник, 30.08.2011, 10:58
 
Ответить
СообщениеAlex_ST,
Quote (Alex_ST)
Конечно, если речь идёт об обработке массивов из десятков-сотен тысяч строк, то имеет смысл "ловить блох" на таком мизерном ускорении процедуры

не стану спорить, эфффект - мизерный. Это так - от тяги к перфекционизму.

Quote (Alex_ST)
Да и вообще: перед анализом хорошо бы провести "чистку" массива - убрать лишние пробелы и, наверное, знаки препинания

Боюсь чистка массива займёт не меньше времени, чем само сравнение. smile
FindBestMatchTxt обращается к каждой ячейке диапазона только 1 раз и грузит её текст в промежуточную строку txt. Так что, не уверен. что предварительная загрузка всех ячеек в массив типа Array (если я правильно понял эту мысль) даст заметный эффект.

Quote (Alex_ST)
2. Записи массива поочерёдно сравнивать с образцом функцией TextSimilarity.

В FindBestMatchTxt происходит более сложный предварительный анализ искомого текста, что сильно ускоряет последующие циклы сравнения, и делается это 1 раз. А TextSimilarity будет свою простенькую подготовку выполнять многократно и само сравнение будет выполнять медленнее.

Quote (Alex_ST)
3. Каждый лучший чем предыдущий по проценту совпадения результат записывать в пару переменных "процент" и "строка". По окончании анализа массива в переменной "строка" будет текст наиболее похожей на образец строки.

Так оно и происходит: best - это "процент", вместо "строки" - её порядковый номер txtNum запоминается прямо в возвращаемой переменной.

Было бы очень любопытно, если бы вы провели независимое сравнение производительности поиска через TextSimilarity и через FindBestMatchTxt. А то наворотов я там оптимизирующих навешал, а какой от них реальный эффект - толком неизвестно.

Автор - Формуляр
Дата добавления - 30.08.2011 в 10:51
Alex_ST Дата: Вторник, 30.08.2011, 12:34 | Сообщение № 19
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Формуляр,
я не хочу использовать FindBestMatchTxt потому, что она возвращает только одно значение, которое ПО ЕЁ МНЕНИЮ мне больше всего подходит.
А я хочу доверить функции нечёткого поиска только приблизительную предварительную фильтрацию записей чтобы из результатов иметь возможность уже САМОМУ ВЫБРАТЬ наиболее подходящий мне вариант.
Чистку массива от лишних пробелов (лидирующих, финиширующих, внутренних) можно, ИМХО, сделать всего один раз и даже прямо на листе "одним махом" применив Application.WorksheetFunction.Trim сразу ко всем ячейкам фильтруемого диапазона (нечего грязь на листе хранить!).
Для удаления знаков пунктуации из записей массива можно применить регулярные выражения (RegExp). Тоже только один раз. И это тоже недолго.
А работа с массивом ВСЕГДА даёт выигрыш в скорости чуть ли не на порядок по сравнению с работой непосредственно с ячейками.
Поэтому если записей в фильтруемом диапазоне не сотни, а десятки тысяч, то выигрыш будет значительным.



С уважением,
Алексей
MS Excel 2003 - the best!!!
 
Ответить
СообщениеФормуляр,
я не хочу использовать FindBestMatchTxt потому, что она возвращает только одно значение, которое ПО ЕЁ МНЕНИЮ мне больше всего подходит.
А я хочу доверить функции нечёткого поиска только приблизительную предварительную фильтрацию записей чтобы из результатов иметь возможность уже САМОМУ ВЫБРАТЬ наиболее подходящий мне вариант.
Чистку массива от лишних пробелов (лидирующих, финиширующих, внутренних) можно, ИМХО, сделать всего один раз и даже прямо на листе "одним махом" применив Application.WorksheetFunction.Trim сразу ко всем ячейкам фильтруемого диапазона (нечего грязь на листе хранить!).
Для удаления знаков пунктуации из записей массива можно применить регулярные выражения (RegExp). Тоже только один раз. И это тоже недолго.
А работа с массивом ВСЕГДА даёт выигрыш в скорости чуть ли не на порядок по сравнению с работой непосредственно с ячейками.
Поэтому если записей в фильтруемом диапазоне не сотни, а десятки тысяч, то выигрыш будет значительным.

Автор - Alex_ST
Дата добавления - 30.08.2011 в 12:34
Alex_ST Дата: Вторник, 30.08.2011, 14:18 | Сообщение № 20
Группа: Друзья
Ранг: Участник клуба
Сообщений: 3206
Репутация: 609 ±
Замечаний: 0% ±

2003
Вот. Максимально причесал. Добавил чистку от пробелов и пунктуации с помощью RegExp.
Требуемую степень сходства теперь можно удобно регулировать движком полоски прокрутки (но можно и в ручную).
Пока другие методы удалять не стал на всякий случай.
К сообщению приложен файл: FUZZY_SEARCHING.zip (59.4 Kb)



С уважением,
Алексей
MS Excel 2003 - the best!!!


Сообщение отредактировал Alex_ST - Вторник, 30.08.2011, 14:19
 
Ответить
СообщениеВот. Максимально причесал. Добавил чистку от пробелов и пунктуации с помощью RegExp.
Требуемую степень сходства теперь можно удобно регулировать движком полоски прокрутки (но можно и в ручную).
Пока другие методы удалять не стал на всякий случай.

Автор - Alex_ST
Дата добавления - 30.08.2011 в 14:18
Мир MS Excel » Вопросы и решения » Готовые решения » Простая метрика сходства текстовых строк (Нечеткий поиск - варианты решения)
  • Страница 1 из 11
  • 1
  • 2
  • 3
  • 10
  • 11
  • »
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!