たとえば、luaで次のようなことをしたいと思います。
s = "Hey\n There And Yea\n"
print(s.rfind("\n", 0, 5))
string.find関数を使用してluaでこれを作成してみました:
local s = "Hey\n There And Yea\n"
local _, p = s:find(".*\n", -5)
print(p)
しかし、これらは同じ結果を生み出していません。何が間違っているのでしょうか。これを修正してrfindと同じにする方法を教えてください。
私が書いたパターンは、askerがテストケースとして使用したような単一文字の部分文字列に対してのみ機能します。次の太字のヘッダーにスキップしてその答えを確認するか、彼らが試みで間違ったことのいくつかの説明を読んでください。複数文字の部分文字列の一般的で非効率的なソリューションについては、最後の太字ヘッダーにスキップしてください
mystring.rfind
luaを使用してPythonの出力を再作成しようとしましたがmystring:find
、これは1文字の部分文字列に対してのみ機能します。後で、すべての場合にそれを実行するが、かなり悪いループである関数を紹介します。
要約として(あなたが間違っていることに対処するために)mystringvar:find("pattern", index)
、砂糖について話しましょうstring.find(mystringvar, "pattern", index)
。これにより、start, stop
インデックスが返されます。
オプションのインデックスは、終了ではなく開始を設定しますが、負のインデックスは「右マイナスインデックス」から文字列の終了まで逆方向にカウントします(インデックス-1は最後の文字のみを評価し、-2は最後の2を評価します)。これは望ましい動作ではありません。
インデックスを使用して部分文字列を作成する代わりに、次のような部分文字列を作成する必要があります。
mystringvar:sub(start, end)
最初から最後まで部分文字列を抽出して返します(1つのインデックス付きの終わりを含む)。したがって、Pythonの0-5(0インデックス付き、排他的終了)を再作成するには、1-5を使用します。
これらのメソッドは連鎖することができますstring:sub(x, y):find("")
が、読みやすくするために分割することに注意してください。それ以上の苦労なしに、私はあなたに提示します:
答え
local s = "Hey\n There And Yea\n"
local substr = s:sub(1,5)
local start, fin = substr:find("\n[^\n]-$")
print(start, ",", fin)
いくつかの半分の測定ソリューションがありましたが、私が書いているものが複数の部分文字列インスタンス(1〜5の部分文字列には1つしか含まれていない)で機能することを確認するために、部分文字列と文字列全体でテストしました。観察:
sub(1、5)での出力:sub(1、19 )での4 , 5
出力(全長):19 , 19
これらは両方とも右端の部分文字列の始まりを正しく報告しますが、「fin」インデックスは文の終わりに行くことに注意してください。後で説明します。とにかくrfindは開始インデックスのみを返すので、これで問題ないことを願っています。したがって、これは適切な置換であるはずです。
コードを読み直して、どのように機能するかを見てみましょう。sub
すでに説明しまし
たstring.findにインデックスは
もう必要ありません"\n[^\n]-$"
。このパターンは何ですか?
$
-文の終わりにアンカーします
[^x]
-「xではありません」に
-
一致します-前の文字またはセット(この場合は[^\n]
)の一致をできるだけ少なくします(0でも)。これは、文字列が部分文字列で終わっていても機能することを意味します)
\ nで始まるので、まとめると次のようになります。「文の終わりまで、改行を見つけてください。その後に改行はありません。 。」つまり、部分文字列に含まれる\ nのインスタンスは1つだけですが、複数の部分文字列を持つ文字列でこの関数を使用すると、rfindと同様に、最高のインデックスが得られます。
string.findはパターングループ(()
)に準拠していないため\n
、をグループでラップするのは無駄であることに注意してください。結果として、エンドアンカー$
がfin
変数を文の終わりまで拡張するのを止めることはできません。
これがあなたにとってうまくいくことを願っています。
任意の長さの部分文字列に対してこれを行う関数これについては
説明しません。
function string.rfind(str, substr, plain) --plain is included for you to pass to find if you wish to ignore patterns
assert(substr ~= "") --An empty substring would cause an endless loop. Bad!
local plain = plain or false --default plain to false if not included
local index = 0
--[[
Watch closely... we continually shift the starting point after each found index until nothing is left.
At that point, we find the difference between the original string's length and the new string's length, to see how many characters we cut out.
]]--
while true do
local new_start, _ = string.find(str, substr, index, plain) --index will continually push up the string to after whenever the last index was.
if new_start == nil then --no match is found
if index == 0 then return nil end --if no match is found and the index was never changed, return nil (there was no match)
return #str - #str:sub(index) --if no match is found and we have some index, do math.
end
--print("new start", new_start)
index = new_start + 1 --ok, there was some kind of match. set our index to whatever that was, and add 1 so that we don't get stuck in a loop of rematching the start of our substring.
end
end
あなたは私のために全体の「テスト・スイート」を参照したい場合は、これを...
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加