2 回答

TA貢獻1946條經驗 獲得超3個贊
Lua 有一個鮮為人知的函數string.reverse,可以反轉字符串中的所有字符。雖然很少需要這樣做,但該函數通??捎糜谠谧址畠冗M行反向搜索。因此,要實現rfind,您需要在反向原始字符串中搜索反向模式,最后進行一些算術以獲得與原始字符串的偏移量。這是模仿 Python 的代碼:rfind
function rfind(subject, tofind, startIdx, endIdx)
startIdx = startIdx or 0
endIdx = endIdx or #subject
subject = subject:sub(startIdx+1, endIdx):reverse()
tofind = tofind:reverse()
local idx = subject:find(tofind)
return idx and #subject - #tofind - idx + startIdx + 1 or -1
end
print(rfind("Hello World", "H")) --> 0
print(rfind("Hello World", "l")) --> 9
print(rfind("foo foo foo", "foo")) --> 8
print(rfind("Hello World", "Toto")) --> -1
print(rfind("Hello World", "l", 1, 4)) --> 3
請注意,此版本rfind使用 Python 索引約定,從 開始,如果未找到字符串則0返回。在 Lua 中使用基于 1 的索引并在沒有匹配時-1返回會更加連貫。nil修改將是微不足道的。

TA貢獻1816條經驗 獲得超4個贊
我編寫的模式僅適用于單字符子字符串,例如提問者用作測試用例的子字符串。跳到下一個粗體標題以查看答案,或者繼續閱讀以了解他們在嘗試中做錯的一些事情的解釋。跳到最后的粗體標題,以獲得多字符子字符串的通用、低效解決方案
我嘗試mystring.rfind使用 lua重新創建 python 的輸出mystring:find,它僅適用于單字符子字符串。稍后我將向您展示一個適用于所有情況的函數,但這是一個非常糟糕的循環。
作為回顧(為了解決你做錯的事情),讓我們來談談mystringvar:find("pattern", index), 的糖string.find(mystringvar, "pattern", index)。這將返回start, stop索引。
可選的 Index 設置開始,而不是結束,但負索引將從“右減索引”向后計數到字符串末尾(索引 -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) 輸出: 4 , 5
用 sub(1, 19) 輸出(整個長度):19 , 19
它們都正確地報告了最右邊子字符串的開頭,但請注意,“fin”索引位于句子的末尾,我將在稍后解釋。我希望這沒問題,因為 rfind 無論如何都只返回起始索引,所以這應該是一個合適的替代品。
讓我們重讀一下代碼,看看它是如何工作的:
sub 我已經解釋過了
string.find 中不再需要索引 好吧
,這個模式是什么"\n[^\n]-$"?
$- 錨定到句子末尾
[^x]- 匹配“not x”
-- 前一個字符或集合(在本例中為 )的匹配盡可能少(甚至 0)[^\n]。這意味著如果一個字符串以您的子字符串結尾,它仍然可以工作)
它以 \n 開頭,所以總的來說它的意思是:“給我一個換行符,但后面沒有其他換行符,直到句子結尾”。這意味著即使您的子字符串僅包含 1 個 \n 實例,如果您要在具有多個子字符串的字符串上使用此函數,您仍然會獲得最高索引,就像 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
如果您想查看我的整個“測試套件” ......
添加回答
舉報