文字列があるとします
local a = "Hello universe"
部分文字列「宇宙」を見つける
a:find("universe")
さて、文字列が
local a = "un#verse"
検索する文字列はユニバースです。ただし、部分文字列は 1 文字異なります。したがって、明らかにLuaはそれを無視します。
一文字違いでも文字列を検索させるにはどうすればよいですか?
文字列があるとします
local a = "Hello universe"
部分文字列「宇宙」を見つける
a:find("universe")
さて、文字列が
local a = "un#verse"
検索する文字列はユニバースです。ただし、部分文字列は 1 文字異なります。したがって、明らかにLuaはそれを無視します。
一文字違いでも文字列を検索させるにはどうすればよいですか?
文字がどこにあるかがわかっている場合は、.
その文字の代わりに使用します。a:find("un.verse")
ただし、あいまい文字列検索を探しているようです。Luastring
ライブラリの範囲外です。この記事から始めることをお勧めします:http://ntz-develop.blogspot.com/2011/03/fuzzy-string-search.html
Luaあいまい検索の実装について—私は何も使用していませんが、「luaあいまい検索」をグーグルで検索するといくつかの結果が得られます。いくつかはこの論文に基づいています:http://web.archive.org/web/20070518080535/http ://www.heise.de/ct/english/97/04/386/
https://github.com/ajsher/luafuzzyを試してください。
TREの行に沿って何かが必要なようです:
TRE は、軽量で堅牢、かつ効率的な POSIX 準拠の正規表現マッチング ライブラリであり、近似 (ファジー) マッチングなどの優れた機能を備えています。
近似パターン マッチングを使用すると、一致を近似することができます。つまり、ある程度の近さで一致を検索パターンに近づけることができます。TRE は編集距離尺度 (レーベンシュタイン距離とも呼ばれます) を使用します。この距離では、検索されたテキストで文字を挿入、削除、または置換して、完全に一致させることができます。挿入、削除、または置換ごとに、一致の距離またはコストが追加されます。TRE は、特定のしきい値よりもコストが低い一致を報告できます。TRE を使用して、コストが最も低い一致を検索することもできます。
そのための Lua バインディングはlrexlibの一部として利用できます。
独自の単純なロール アプローチ (パターンが同じ長さを維持するという仮定に基づく):
function hammingdistance(a,b)
local ta={a:byte(1,-1)}
local tb={b:byte(1,-1)}
local res = 0
for k=1,#a do
if ta[k]~=tb[k] then
res=res+1
end
end
print(a,b,res) -- debugging/demonstration print
return res
end
function fuz(s,pat)
local best_match=10000
local best_location
for k=1,#s-#pat+1 do
local cur_diff=hammingdistance(s:sub(k,k+#pat-1),pat)
if cur_diff < best_match then
best_location = k
best_match = cur_diff
end
end
local start,ending = math.max(1,best_location),math.min(best_location+#pat-1,#s)
return start,ending,s:sub(start,ending)
end
s=[[Hello, Universe! UnIvErSe]]
print(fuz(s,'universe'))
免責事項:お勧めしません。楽しみのためだけです:
より良い構文が必要な場合 (標準型のメタテーブルをいじっても構わない場合) は、次のように使用できます。
getmetatable('').__sub=hammingdistance
a='Hello'
b='hello'
print(a-b)
ただし、この方法でa-b
は等しくないことに注意してください。b-a
単一の文字の違いを本当に探していて、パフォーマンスを気にしない場合は、次の簡単な方法を使用できます。
local a = "Hello un#verse"
local myfind = function(s,p)
local withdot = function(n)
return p:sub(1,n-1) .. '.' .. p:sub(n+1)
end
local a,b
for i=1,#s do
a,b = s:find(withdot(i))
if a then return a,b end
end
end
print(myfind(a,"universe"))