Сопоставление строк в VBA с использованием предопределенной функции - PullRequest
0 голосов
/ 12 июля 2020

У меня есть следующие данные, которые я хочу сопоставить, и после прохождения нескольких техник наиболее подходящим оказался метод расстояния Левенштейна - согласны ли вы с этим подходом на основе данных ниже или порекомендуете какой-либо другой метод, который иметь возможность лучше сопоставить следующее в больших объемах?

Пример данных можно увидеть ниже:

**Column1**                                               **Column2**
Modra Digest (DC)                                     Oldstewart2
South West Local /Sunday Times (new)                  Oldstewart
OldStewart political print  Saigon                    Last month Saigon Last month
Oldstewart2 Local print (Former)                      Modra Digest Velehrad Digest (DC) (used via Bembek) 
Saigon Last month                                     South West Local South West Local /Sunday Times

ввод данных

Если я решу на go заранее использовать метод расстояния Левенштейна (определяемый как функция в VBA под названием Левенштейн, где результаты преобразуются в результаты в проценты), я хотел бы немного настроить применение этой функции и запустить его. как макрос. Столбцы, которые я сопоставляю (A и B), имеют разное количество входов, которые различаются по структуре (т.е. даже при сортировке по алфавиту совпадающие элементы не будут рядом друг с другом. Можно ли сделать следующее?

  1. Временно удалите все в скобках и его содержимое из обеих сравниваемых строк и ОБРЕЗЬТЕ строки, чтобы удалить пустое пространство до и после оставшейся строки.
  2. Удалите все повторяющиеся слова из каждой строки.
  3. Найдите совпадение Левенштейна из (A и B) на основе наивысшего процента сходства (в соответствии с заданной функцией) и расположите соответственно в столбцах A и B, чтобы «наиболее подходящие элементы» были размещены рядом с друг друга.
  4. Показать исходную форму (т.е. включая скобки, дубликаты слов) в структуре, описанной в пункте 3, однако без необходимости повторного вычисления (т.е. процент совпадения должен быть сохранен из TRIMmed, дедупликации и форму без скобок, как указано в пункте 1 и 2)
  5. Список записей записей должен быть отсортирован от наиболее подходящих к наименее подходящим.

Наконец (здесь я считаю выбранный подход немного сомнительным), поскольку приведенное выше упомянутый метод подсчитывает количество изменений, которые необходимо сделать для соответствия строкам, что было бы наилучшим способом (возможно, еще один уровень проверки) для работы с такими примерами, как «oldsteward» против «Oldstewart2 Local print (бывший)», так как это потребует удаления текста, который считается изменением (что снижает сходство) и, следовательно, будет иметь низкое сходство согласно методу Левенштейна?

Что касается использования метода Левенштейна, результат будет выглядеть примерно так:

****Column1**                       **Column2**                                          **Match(%)**
Modra Digest (DC)                       Modra Digest Velehrad Digest (DC) (used via Bembek)     63
South West Local /Sunday Times (new)    South West Local South West Local /Sunday Times         64
OldStewart political print              Oldstewart                                              38
Oldstewart2 Local print (Former)        Oldstewart2                                             48
Saigon Last month                       Saigon Last month Saigon Last month                     94

Вывод данных

Функция:

Function Levenshtein3(ByVal string1 As String, ByVal string2 As String) As Long

Dim i As Long, j As Long, string1_length As Long, string2_length As Long
Dim distance(0 To 90, 0 To 80) As Long, smStr1(1 To 90) As Long, smStr2(1 To 800) As Long
Dim min1 As Long, min2 As Long, min3 As Long, minmin As Long, MaxL As Long

string1_length = Len(string1):  string2_length = Len(string2)

distance(0, 0) = 0
For i = 1 To string1_length:    distance(i, 0) = i: smStr1(i) = Asc(LCase(Mid$(string1, i, 1))): Next
For j = 1 To string2_length:    distance(0, j) = j: smStr2(j) = Asc(LCase(Mid$(string2, j, 1))): Next
For i = 1 To string1_length
    For j = 1 To string2_length
        If smStr1(i) = smStr2(j) Then
            distance(i, j) = distance(i - 1, j - 1)
        Else
            min1 = distance(i - 1, j) + 1
            min2 = distance(i, j - 1) + 1
            min3 = distance(i - 1, j - 1) + 1
            If min2 < min1 Then
                If min2 < min3 Then minmin = min2 Else minmin = min3
            Else
                If min1 < min3 Then minmin = min1 Else minmin = min3
            End If
            distance(i, j) = minmin
        End If
    Next
Next

' Levenshtein3 will properly return a percent match (100%=exact) based on similarities and Lengths etc...
MaxL = string1_length: If string2_length > MaxL Then MaxL = string2_length
Levenshtein3 = 100 - CLng((distance(string1_length, string2_length) * 100) / MaxL)

End Function
  • Расстояние Левенштейна представляет собой строку метри c для измерения разница между двумя последовательностями. Неформально расстояние Левенштейна между двумя словами - это минимальное количество односимвольных правок (т.е. вставок, удалений или замен), необходимых для замены одного слова на другое.

Большое спасибо за вашу помощь.

Джей

...