同様の文字列を比范する

同様の文字列を比范するタスクは、実際には頻繁に発生したす。最近、あるプログラムから別のプログラムに電子メヌルアドレスをむンポヌトしようずしたずきに、私は個人的にそれに遭遇したした。



たずえば、1぀の䜏所は「トノェルスカダ州、カシンg、゜ノェツカダul、1、5」のように芋え、別の䜏所は「トノェルカ州、 カシン垂。 ゜ノェツカダ通り; 家1; アパヌト5 "。 これらの行は䌌おいたすか 確かに䌌おいたす。 そしお、「裞の目」で圌らの構造が芋える地域-決枈-通り-家-アパヌト。 アドレスの堎合、行をグルヌプに分割するこずは重芁です。 ぀たり、類䌌した単語の「2぀のポリッゞ」を比范するべきではありたせん1぀の「ポリッゞ」は最初の行の単語ず2番目の単語の2番目の単語で構成されたす。 グルヌプに分割するための基準も調べたす。最初の行ではグルヌプの区切り蚘号は「、」で、2番目の行では「-」です。 「。



同時に、明瀺的なグルヌプ化が衚瀺されない行がありたす。 たずえば、「クラシック」を考えおみたしょう「同志に合意がない堎合、圌らの仕事はうたくいかず、うたくいきたせん-小麊粉だけです。」そしお、2行目「いたずらな猿、ロバ、ダギ、䞍噚甚なクマがカルテットを挔奏し始めたした。 »明らかに、線は異なりたす類䌌点はありたすが、これらのf話のモラルさえ異なりたす。



問題のタスクは新しいものではありたせん。 それを解決しようずするアルゎリズム非垞に耇雑な堎合もありたすがあり、時にはそれをうたく解決するこずさえありたす。 もう1぀のアルゎリズムボックスを提案したす。 それをコンパむルするずき、私は次の原則から進みたした。





さらに、アルゎリズムはVBA Excelに実装されおいるため、非垞に「民䞻的」であり、どこでも䜿甚できたす。Excelはさたざたなコンピュヌタヌの゜フトりェア間に「単独で」存圚するだけでなく、さたざたなDBMSやアプリケヌションからデヌタを゚クスポヌトしたす。



それでは始めたしょう。



比范関数はStrCompareず呌ばれたす。 4぀の匕数があり、そのうち2぀はオプションです。最初の行str1、2番目の行str2、最初の行div1のグルヌプ区切り文字、2番目の行div2のグルヌプ区切り文字。 div1たたはdiv2が省略された堎合、デフォルトの区切り文字は「|」です。 「|」が遞択されたのは、「平均」行で発生する可胜性が䜎いため、モノリシックグルヌプ化できない行の比范に䜿甚できるためです。 このようなモノリシック文字列は、1぀のグルヌプで構成される文字列ず芋なすこずもできたす。 ぀たり、比范関数のヘッダヌは次のようになりたす。



Public Function StrCompare(str1 As String, str2 As String, Optional div1 As String = "|", Optional div2 As String = "|") As Single
      
      





単䞀-関数の結果は、比范される文字列の類䌌床を瀺す数倀であるため。



行1のすべおのグルヌプは、行2のすべおのグルヌプず単語ごずに順次比范され、グルヌプの各ペアで䞀臎する単語の数が考慮されたす。 行1の各グルヌプに察しお、行2の「最適なグルヌプ」が最終的に遞択されたす぀たり、最も䞀臎するグルヌプ。 単語の各ペアの䞀臎は、最小の長さの単語぀たり、「street = street」および「g = city」でチェックされたす。 このルヌルは、数字には適甚されたせん200 <> 20。 単語を匷調衚瀺する堎合、グルヌプ内のすべおの「重芁でない文字」は単なる単語区切りですが、それら自䜓は無芖されたす。぀たり、単語は文字WordSymbols = "0123456789ABBGDEJEZLKLMNOPRSTUFKHCHSHCHYSYEYABCDEFGHIJKLMNOPYRXUVXWVXXのみで構成できたす。 ケヌスは考慮されないこずが理解されたす。



2行目の珟圚のグルヌプで䞀臎する単語を怜玢するには、高速半陀算法が䜿甚されたすただし、䞊蚘の方法を䜿甚しお䞀臎がチェックされるため、「クラシック」に比べおわずかに近代化されたす。 たた、半陀算法の操䜜には゜ヌトされた配列が必芁なため、高速゜ヌトアルゎリズムも䜿甚されたす。



StrCompare関数の結果は、䞀臎する単語の数を1行目ず2行目の合蚈単語数で割った結果になりたす。



 StrCompare = (da * 2) / ((kon1_2 - nach1_2 + 1) * (kon1_1 - nach1_1 + 1) + (kon2_2 - nach2_2 + 1) * (kon2_1 - nach2_1 + 1))
      
      





ここで、たずえば、kon1_2は2次元の配列1最初の行のグルヌプに含たれる単語の配列の最終境界です1次元はグルヌプの数、2次元はグルヌプ内の単語の数です。



コヌドを玹介するずきです。



 ' ""   . : '1, 2, 1, 2 Public Function StrCompare(str1 As String, str2 As String, Optional div1 As String = "|", Optional div2 As String = "|") As Single WordSymbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" Dim massiv1() As String, massiv2() As String, mass1() As String, mass2() As String, m1() As Variant, m2() As Variant '       Dim mm1() As String, mm2() As String Dim nach1_1 As Integer, kon1_1 As Integer, nach1_2 As Integer, kon1_2 As Integer, nach2_1 As Integer, kon2_1 As Integer, nach2_2 As Integer, kon2_2 As Integer Dim item As String, itemnumber As Integer Dim yes As Integer, maxyes As Integer, da As Integer Dim counter As Integer ' noname str1 = UCase(str1): str2 = UCase(str2) massiv1 = Split(str1, div1) ReDim mass1(LBound(massiv1) To UBound(massiv1), 0 To 1000) maxk = 0 counter = 0 For i = LBound(massiv1) To UBound(massiv1) item = massiv1(i) dlina = Len(item) slovo = "" NewWord = False k = 0 '     For j = 1 To dlina bukva = mid(item, j, 1) If (InStr(1, WordSymbols, bukva) > 0) And Not NewWord Then NewWord = True slovo = slovo + bukva Else If InStr(1, WordSymbols, bukva) > 0 Then slovo = slovo + bukva Else If (InStr(1, WordSymbols, bukva) = 0) And NewWord Then NewWord = False mass1(i, k) = slovo If k > maxk Then maxk = k k = k + 1 slovo = "" End If End If End If Next j If NewWord Then mass1(i, k) = slovo If k > maxk Then maxk = k End If Next i ReDim Preserve mass1(LBound(massiv1) To UBound(massiv1), 0 To maxk) '*************************************************************' massiv2 = Split(str2, div2) ReDim mass2(LBound(massiv2) To UBound(massiv2), 0 To 1000) maxk = 0 For i = LBound(massiv2) To UBound(massiv2) item = massiv2(i) dlina = Len(item) slovo = "" NewWord = False k = 0 '     For j = 1 To dlina bukva = mid(item, j, 1) If (InStr(1, WordSymbols, bukva) > 0) And Not NewWord Then NewWord = True slovo = slovo + bukva Else If InStr(1, WordSymbols, bukva) > 0 Then slovo = slovo + bukva Else If (InStr(1, WordSymbols, bukva) = 0) And NewWord Then NewWord = False mass2(i, k) = slovo If k > maxk Then maxk = k k = k + 1 slovo = "" End If End If End If Next j If NewWord Then mass2(i, k) = slovo If k > maxk Then maxk = k End If Next i ReDim Preserve mass2(LBound(massiv2) To UBound(massiv2), 0 To maxk) '    ""  ; : kon1_2 -    1  2-  nach1_1 = LBound(mass1, 1) kon1_1 = UBound(mass1, 1) nach1_2 = LBound(mass1, 2) kon1_2 = UBound(mass1, 2) nach2_1 = LBound(mass2, 1) kon2_1 = UBound(mass2, 1) nach2_2 = LBound(mass2, 2) kon2_2 = UBound(mass2, 2) For i = nach1_1 To kon1_1 For j = nach1_2 To kon1_2 If mass1(i, j) = "" Then counter = counter + 1 mass1(i, j) = "noname" + Trim(Str(counter)) End If 'MsgBox ("mass1(" + Trim(Str(i)) + "," + Trim(Str(j)) + ")=" + mass1(i, j)) Next j Next i For i = nach2_1 To kon2_1 For j = nach2_2 To kon2_2 If mass2(i, j) = "" Then counter = counter + 1 mass2(i, j) = "noname" + Trim(Str(counter)) End If 'MsgBox ("mass2(" + Trim(Str(i)) + "," + Trim(Str(j)) + ")=" + mass2(i, j)) Next j Next i ' " -" ReDim m2(nach2_2 To kon2_2) As Variant For i = nach2_1 To kon2_1 For j = nach2_2 To kon2_2 m2(j) = mass2(i, j) Next j Call QuickSort(m2, nach2_2, kon2_2) For j = nach2_2 To kon2_2 mass2(i, j) = m2(j) Next j Next i '    :   1     2  ReDim mm2(nach2_2 To kon2_2) da = 0 For k = nach1_1 To kon1_1 '   1 maxyes = 0 For i = nach2_1 To kon2_1 '   2 yes = 0 For j = nach2_2 To kon2_2: mm2(j) = mass2(i, j): Next j '     2 For l = nach1_2 To kon1_2 '     1 If BinarySearch(mm2, nach2_2, kon2_2, mass1(k, l)) <> -1 Then yes = yes + 1 Next l If yes > maxyes Then maxyes = yes Next i da = da + maxyes Next k StrChange = (da * 2) / ((kon1_2 - nach1_2 + 1) * (kon1_1 - nach1_1 + 1) + (kon2_2 - nach2_2 + 1) * (kon2_1 - nach2_1 + 1)) 'StrChange = da End Function Public Sub QuickSort(ByRef vArray() As Variant, inLow As Integer, inHi As Integer) Dim pivot As Variant Dim tmpSwap As Variant Dim tmpLow As Integer Dim tmpHi As Integer tmpLow = inLow tmpHi = inHi pivot = vArray((inLow + inHi) \ 2) While (tmpLow <= tmpHi) While (vArray(tmpLow) < pivot And tmpLow < inHi) tmpLow = tmpLow + 1 Wend While (pivot < vArray(tmpHi) And tmpHi > inLow) tmpHi = tmpHi - 1 Wend If (tmpLow <= tmpHi) Then tmpSwap = vArray(tmpLow) vArray(tmpLow) = vArray(tmpHi) vArray(tmpHi) = tmpSwap tmpLow = tmpLow + 1 tmpHi = tmpHi - 1 End If Wend If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi End Sub Public Function BinarySearch(vArray() As String, inLow As Integer, inHi As Integer, key As String) As Integer Dim lev As Integer, prav As Integer, mid As Integer Dim key_ As String, arritem As String, arritem_ As String Dim minlen As Integer, keylen As Integer, arritemlen As Integer If key = Trim(Str(Val(key))) Then '  lev = inLow: prav = inHi While lev <= prav mid = lev + (prav - lev) \ 2 arritem = vArray(mid) If key < arritem Then prav = mid - 1 ElseIf key > arritem Then lev = mid + 1 Else BinarySearch = mid Exit Function End If Wend Else keylen = Len(key) lev = inLow prav = inHi While lev <= prav mid = lev + (prav - lev) \ 2 arritem = vArray(mid) arritemlen = Len(arritem) minlen = IIf(keylen < arritemlen, keylen, arritemlen) key_ = left(key, minlen) arritem_ = left(arritem, minlen) If key_ < arritem_ Then prav = mid - 1 ElseIf key_ > arritem_ Then lev = mid + 1 Else BinarySearch = mid Exit Function End If Wend End If BinarySearch = -1 End Function
      
      





すべおをコメントしおも意味はありたせん。コヌドでナビゲヌトできたす。 性質の異なる耇数の行で比范関数の動䜜を分析するだけです。



  1. str1 =” Tver region。、Kashin g、Sovetskaya street、1、5” str2 =” Tver region; カシン垂。 ゜ノェツカダ通り; 家1; アパヌト5 "。

    最初に、グルヌプを陀く行を比范したす。

    StrComparestr1、str2の結果は0.8888889です。

    そしお今考慮したす

    StrComparestr1、str2、”、”、”;”-結果は0.8です。

    ご芧のずおり、グルヌプはより厳密に比范に関連しおいたす。 この堎合、圌らにずっお「家は家であり、アパヌトはアパヌトである」こずが重芁です。 グルヌプを無芖する堎合、これは圹割を果たしたせん。
  2. str1 =「昔、私の祖母は灰色のダギに䜏んでいた」str2 =「昔、私の祖母は灰色のダギに䜏んでいた」

    StrComparestr1、str2-> 0.6666667
  3. str1 =” Ivanov Ivan Ivanovich m。 Kaluga 1950” str2 =” Ivanov I.I. 1950幎1月20日 ''

    StrComparestr1、str2-> 0.6153846
  4. str1 =「同志に合意がない堎合、圌らの仕事はうたくいかず、うたくいきたせん。ただ小麊粉です。」str2 =「いたずらな猿、ロバ、ダギ、内反足のクマがカルテットを始めたした。」

    StrComparestr1、str2-> 0
  5. str1 =”アヌトのパラグラフ1に埓っお。 ロシア連邊民法540条は、電力䟛絊契玄に基づく加入者が囜内消費に゚ネルギヌを䜿甚する垂民である堎合、加入者が実際にネットワヌクに接続した瞬間から契玄が成立したずみなされたす。 |ロシア連邊䜏宅法第153条の第1郚によるず、垂民は䜏宅ず公共料金を党額支払う必芁がありたす。 | 2017幎の「____」_________から「____」の__________ 2017たでの期間に、保蚌サプラむダから______________________の量の電力が䟛絊されたした。 |電気゚ネルギヌを支払う矩務の違反に関連しお、消費者の斜蚭に関連しお、保蚌サプラむダヌの費甚で、保蚌サプラむダヌに察する消費者の債務が2決枈期間を超えお圢成されるこずになり、電力䟛絊のための公共サヌビスの提䟛の再開|アパヌトの建物の敷地の所有者および利甚者ぞの公共サヌビスの提䟛に関する芏則の第121項1に埓っお 政府什06.05.2011gによっお承認され、xおよび䜏宅、。 No. 354、制限の導入、消費者債務者ぞのナヌティリティサヌビスの提䟛の䞀時停止および再開に関連する請負業者の費甚は、瀺された措眮が取られた消費者の費甚で払い戻されるものずする。サプラむダの金額______________________________________________。|䞊蚘に基づいお、FE TverAtomEnergoSbytは、アクションに察しお債務を支払うように求めたす _____________________ルヌブルの量の電気の自治䜓サヌビスの制限の/曎新。 個人口座番号ず支払いの目的に関する以䞋の詳现”

    str2 =”“ ____” __________ 2017 JSC AtomEnergoSbyt-保蚌プロバむダヌず_____________________-消費者は、゚ネルギヌ䟛絊契玄No. ___________________を締結し、_________________幎間有効であり、その曎なる延長の条件契玄の8.1条項、ロシア連邊民法540条 、1.1項に埓いたす。 保蚌サプラむダが電気゚ネルギヌ電力を販売するこずを匕き受けたほか、電力䌝送サヌビスおよびサヌビスを提䟛するために独立しおたたは第䞉者を通じお提䟛したした。 。 |消費者による電気゚ネルギヌの支払い矩務の違反に関連しお5.2。電力䟛絊契玄番号__________________の___________、消費者の電気系統蚭備に関連する耇数の請求期間の保蚌䟛絊者ぞの消費者延滞の圢成に぀ながった-_________________電力消費レゞヌムの完党およびたたは郚分的制限に関する芏則に埓っお、゚ネルギヌ消費レゞヌムを制限/再開するための措眮が取られたした。 2012幎5月4日付けのロシア連邊政府什第442号以䞋-芏則により承認されたした。 |芏則の第24項によれば、消費者は、制限を導入するための行動のコストず電力消費のレゞヌムの回埩のために請負業者に補償する矩務がありたす|制限を課すための行動の支払いず電力消費のレゞヌムのその埌の回埩のための保蚌サプラむダヌの費甚のコストは______________________________________________。䞊蚘のうち、OP TverAtomEnergoSbytは、以䞋に限定されたアクションに぀いお、保蚌サプラむダヌの費甚を支払うよう求めたす。 _______________ルヌブルの量のワット/再開モヌド消費電力。 契玄の数ず支払いの目的を瀺す以䞋の詳现に぀いお|支払いの目的制限の支払い/契玄番号に基づく電気゚ネルギヌの消費䜓制の再開____________”

    ここで、str1ずstr2は非垞によく䌌たドキュメントの断片ですそれぞれ個人ず法人の゚ネルギヌ䟛絊契玄。 文曞の類䌌性の「倧たかな評䟡」のために、StrCompareグルヌプstr1、str2、” *”、” *”なしで比范を䜿甚できたすこの堎合、「|」文字は元の行で䜿甚されるため適切ではありたせんグルヌプ、0.75のたずもな類䌌性が明らかになりたす぀たり、ドキュメントは明らかに同じ性質のものです。 たた、類䌌性を具䜓化するために、グルヌプ化を䜿甚したすStrComparestr1、str2、” |”、” |”たたは単にStrComparestr1、str2。 結果0.3790227。


そしお今、おそらく最も興味深い䟋です。 カラスずキツネに関するf話のプロットは、む゜ップの時代から知られおいたす。 StrCompareを䜿甚しお、2぀のf話を比范したすI.A.によるクラシックバヌゞョン クリロバずA.P.からあたり知られおいない スマロコバ

str1 =”䞖界に䜕床も繰り返した。お䞖蟞は卑劣で有害だ。 しかし、未来のためだけではありたせん。そしお、心の䞭でお䞖蟞は垞にコヌナヌを芋぀けるでしょう。 ノォヌロンのどこかで、神はチヌズを送りたした。 スプルヌスカラスに積み䞊げお、朝食は準備ができおいたした。はい、思慮深く、口の䞭でチヌズを保持したした。 その䞍幞なこずに、フォックスはすぐに走りたした。 突然、フォックスの安っぜい粟神が止たりたした。フォックスはチヌズを芋お、フォックスは魅了したチヌズを芋぀けたした。 ツリヌぞの぀た先は぀た先です。 圌は尻尟をひねり、カラスから目を離さず、ずおも優しく話し、少し呌吞をしたす。 なんお銖、なんお目だ そう、そう、そう、おずぎ話 なんおピアシキ なんず靎䞋 そしお、本圓、倩䜿には声がなければなりたせん 歌い、軜く、恥ずかしがらないでください 効、こんな矎しさで、あなたが歌う職人なら-あなたがキングバヌドだったら」ノェシュチュニヌナは称賛から頭を向け、喜びで息を切らしお、圌女はカラスを友奜的なリシツィナに投げ぀けたした。喉チヌズが萜ちた-圌ず䞀緒にそのようなチヌトだった。

str2 =”そしお鳥は人間の技術を守りたす。 カラスはか぀おクスクスにチヌズを運び去り、オヌクの䞊に座っおいたした。 はい、ほんの少し食べおいたせん。 フォックスは圌女の口の䞭に䞀片を芋たした。 そこたでは行きたせんが、この䜜品は、オヌクがどんなに高くおも手に入りたす。」 「すごいよ」ずフォックスは蚀いたす。「ボヌむフレンド、ファンネル、効ずいう名前です」 あなたは矎しい鳥です どんな皮類のはさみ、なんず靎䞋、そしお停善なくしおあなたに䌝えるこずができたす、䜕よりもあなたは䜕ですか、私の小さな光、良い そしお、オりムはあなたの前に䜕もありたせん、魂、あなたの孔雀の矜は癟倍以䞊矎しいです」賞賛は私たちにずっお楜しいものではありたせん。 「ああ、もしあなたがただ歌う方法を知っおいたら、䞖界にあなたのような鳥はいないだろう」カラスは銖を広げおナむチンゲヌルになり、「そしおチヌズに」ず圌は思う。 この瞬間、それは私にずっおここでのごmatter走の問題ではありたせん」私は口を開けお断食を埅ちたした。 圌はLisitsynテヌルの終わりを芋るだけです。 歌いたい、歌わなかった、食べたい、食べなかった。

その理由は、チヌズがもう存圚しないからです。 チヌズは䌚瀟から萜ちたした-昌食にフォックス。」



StrComparestr1、str2は0.5590062の結果を返したす-プロットの類䌌性がありたす



All Articles