查找字符串中字符的最后一个索引。

我想在我的 Lua (Luvit) 项目中使用字符串的 lastIndexOf 方法,但是很遗憾,没有这样的内置方法,我现在有些困惑。

在 JavaScript 中,它看起来像这样:

'my.string.here.'.lastIndexOf('.')     // 返回 14
点赞
用户2806996
用户2806996

查找 haystack 字符串中最后一次出现 needle 字符串的位置:

function findLast(haystack, needle)
    -- 设置 `find()` 方法的第三个参数为false以允许使用模式匹配
    local found = haystack:reverse():find(needle:reverse(), nil, true)
    if found then
        return haystack:len() - needle:len() - found + 2
    else
        return found
    end
end

print(findLast("my.string.here.", ".")) -- 15,因为Lua字符串的索引是从1开始的
print(findLast("my.string.here.", "here")) -- 11
print(findLast("my.string.here.", "there")) -- nil

如果你想查找模式的最后一次出现而不是字符串,将 find() 方法的最后一个参数更改为 false(或删除该参数)。

2013-12-08 22:32:44
用户107090
用户107090
function findLast(haystack, needle)
    local i=haystack:match(".*"..needle.."()")
    if i==nil then return nil else return i-1 end
end

s='my.string.here.'
print(findLast(s,"%."))
print(findLast(s,"e"))

请注意,要查找 .,您需要转义它。

2013-12-08 23:06:13
用户828255
用户828255

如果您关心性能,那么如果您使用使用LuaJIT的Luvit,则会更快一些。

local find = string.find
local function lastIndexOf(haystack, needle)
    local i, j
    local k = 0
    repeat
        i = j
        j, k = find(haystack, needle, k + 1, true)
    until j == nil

    return i
end

local s = 'my.string.here.'
print(lastIndexOf(s, '.')) -- 这将是 15。

请记住,Lua字符串从1开始,而不是JavaScript中的0

2013-12-09 00:24:45
用户441830
用户441830

下面是使用 LPeg 的位置捕获的一个解决方案。

local lpeg      = require "lpeg"
local Cp, P     = lpeg.Cp, lpeg.P
local lpegmatch = lpeg.match

local cache = { }

local find_last = function (str, substr)
  if not (str and substr)
    or str == "" or substr == ""
  then
    return nil
  end
  local pat = cache [substr]
  if not pat then
    local p_substr   = P (substr)
    local last       = Cp() * p_substr * Cp() * (1 - p_substr)^0 * -1
    pat = (1 - last)^0 * last
    cache [substr] = pat
  end
  return lpegmatch (pat, str)
end

find_last() 在字符串 str 中查找子串 substr 的最后一次出现位置,其中 substr 可以是任意长度的字符串。第一个返回值是子串 substr 在字符串 str 中的第一个字符位置,第二个返回值是紧随 substr 后面的第一个字符位置(即等于匹配长度加上第一个返回值)。

用法:

local tests = {
  A    = [[fooA]],                      --> 4, 5
  [""] = [[foo]],                       --> nil
  FOO  = [[]],                          --> nil
  K    = [[foo]],                       --> nil
  X    = [[X foo X bar X baz]],         --> 13, 14
  XX   = [[foo XX X XY bar XX baz X]],  --> 17, 19
  Y    = [[YYYYYYYYYYYYYYYYYY]],        --> 18, 19
  ZZZ  = [[ZZZZZZZZZZZZZZZZZZ]],        --> 14, 17
  --- Accepts patterns as well!
  [P"X" * lpeg.R"09"^1] = [[fooX42barXxbazX]], --> 4, 7
}

for substr, str in next, tests do
  print (">>", substr, str, "->", find_last (str, substr))
end
2013-12-09 01:04:42
用户4364020
用户4364020
可以进行优化,但这个函数很简单并且能够达到预期的效果。

function lastIndexOf(haystack, needle)
  local last_index = 0
  while haystack:sub(last_index+1, haystack:len()):find(needle) ~= nil do
    last_index = last_index + haystack:sub(last_index+1, haystack:len()):find(needle)
  end
  return last_index
end

local s = 'my.string.here.'
print(lastIndexOf(s, '%.')) -- 15
2016-04-29 21:02:21