亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我如何在 Lua 中使用參數實現 rfind ?

我如何在 Lua 中使用參數實現 rfind ?

莫回無 2023-09-05 21:07:15
例如,我想在lua中做這樣的事情:s = "Hey\n There And Yea\n"print(s.rfind("\n", 0, 5))我嘗試在 lua 中使用 string.find 函數進行此操作:local s = "Hey\n There And Yea\n"local _, p = s:find(".*\n", -5)print(p)但這些并沒有產生相同的結果。我做錯了什么,如何解決這個問題,使其與 rfind 相同?
查看完整描述

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修改將是微不足道的。


查看完整回答
反對 回復 2023-09-05
?
繁華開滿天機

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

如果您想查看我的整個“測試套件” ......


查看完整回答
反對 回復 2023-09-05
  • 2 回答
  • 0 關注
  • 237 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號