2013-12-08 14 views
9

Tôi muốn có khả năng sử dụng phương thức lastIndexOf cho các chuỗi trong dự án Lua (Luvit) của tôi. Thật không may là không có phương pháp như vậy được xây dựng trong và tôi là bit bị mắc kẹt ngay bây giờ.Tìm chỉ mục cuối cùng của một ký tự trong một chuỗi

Trong javascript nó trông giống như:

'my.string.here.'.lastIndexOf('.')  // returns 14 
+3

Bạn đang cố giải quyết vấn đề gì? – lhf

+2

Tôi nghĩ cách đơn giản nhất là sử dụng 'string.find'' ('my.string.here.'): Find ("%. [^.] - $") '. nhưng bạn cần thoát khỏi các ký tự đặc biệt (ví dụ: '.',' * ',' + 'v.v.). Ngoài ra trong kết quả Lua nên được 15. – moteus

+0

@moteus gợi ý tốt đẹp, nhưng tôi muốn giải pháp phổ biến (tìm chỉ số cho các con số là tốt, ví dụ) – Kosmetika

Trả lời

10
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")) 

Lưu ý rằng để tìm . bạn cần phải thoát khỏi nó.

3

Để tìm kiếm các ví dụ cuối cùng của chuỗi needle trong haystack:

function findLast(haystack, needle) 
    --Set the third arg to false to allow pattern matching 
    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, because Lua strings are 1-indexed 
print(findLast("my.string.here.", "here")) -- 11 
print(findLast("my.string.here.", "there")) -- nil 

Nếu bạn muốn tìm kiếm các ví dụ cuối cùng của một mô hình thay vào đó, thay đổi đối số cuối cùng thành find thành false (hoặc xóa đối số).

+2

Ví dụ của bạn trả về '1' cho tôi. –

+0

Xin lỗi, từ bộ nhớ - tôi phải quên cách chuỗi Lua hoạt động. – joews

3

Nếu bạn có mối quan tâm về hiệu suất, thì điều này có thể nhanh hơn một chút nếu bạn đang sử dụng Luvit sử dụng LuaJIT.

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, '.')) -- This will be 15. 

Hãy ghi nhớ rằng Lua chuỗi bắt đầu tại 1 thay vì 0 như trong JavaScript.

+0

tìm thấy bài đăng thú vị này về hiệu suất - https://neil.fraser.name/news/2009/12/25/, sự tò mò đã làm câu trả lời này đối phó với hiệu suất - http://stackoverflow.com/a/20460403/2117550? – Kosmetika

+1

@Kosmetika Thật thú vị.Tôi đã không nhìn thấy nó trước đây, nhưng những gì tôi đã viết là rất gần với 'lastIndexOfFind'. Sự khác biệt lớn duy nhất là hàm của tôi trả về 'nil' trái ngược với' -1', đó là kiểu Lua hơn. Oh, và hàm của tôi lấy từ giá trị trả về thứ hai của 'string.find', có nghĩa là nó bỏ qua một số chất nền không cần thiết và về mặt lý thuyết sẽ nhanh hơn. Tôi tin rằng câu trả lời của @ lhf có hiệu quả hơn trên Lua thuần túy và ít hơn trên LuaJIT 2.1 do 'string.match' chưa được biên soạn nhưng mẫu cố định' string.find' là, nhưng bạn sẽ phải thực hiện các bài kiểm tra của riêng mình cho trường hợp sử dụng. –

3

Đây là giải pháp sử dụng tính năng chụp vị trí của 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() thấy sự xuất hiện cuối cùng của substr trong chuỗi str, nơi substr có thể là một chuỗi của bất kỳ chiều dài. Giá trị trả về đầu tiên là vị trí của ký tự đầu tiên của substr trong str, giá trị trả về thứ hai là vị trí của ký tự đầu tiên sau substr (tức là nó tương đương với chiều dài của trận đấu cộng với giá trị trả về đầu tiên).

Cách sử dụng:

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 
0

có thể được tối ưu hóa nhưng đơn giản và thực hiện công việc.

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 
Các vấn đề liên quan