XY-Problem
The X problem of how to best port your code to Lua has been answered by quantumpro already, who optimized it & cleaned it up.
I'll focus on your Y problem:
What's the Lua equivalent of Python endswith
?
Calling string functions, OOP-style
In Lua, strings have a metatable that indexes the global string
library table. String functions are called using str:func(...)
in Lua rather than str.func(...)
to pass the string str
as first "self" argument (see "Difference between .
and :
in Lua").
Furthermore, if the argument to the call is a single string, you can omit the parentheses, turning str:func("...")
into str:func"..."
.
Constant suffix: Pattern Matching
Lua provides a more powerful pattern matching function that can be used to check whether a string ends with a suffix: string.match
. str.endswith("9")
in Python is equivalent to str:match"9$"
in Lua: $
anchors the pattern at the end of the string and 9
matches the literal character 9
.
Be careful though: This approach doesn't work with arbitrary, possibly variable suffices since certain characters - such as $
- are magic characters in Lua patterns and thus have a special meaning. Consider str.endswith(".")
; this is not equivalent to string:match".$"
in Lua, since .
matches any character.
I'd say that this is the lua-esque way of checking whether a string ends with a constant suffix. Note that it does not return a boolean, but rather a match (the suffix, a truthy value) if successful or nil
(a falsey value) if unsuccessful; it can thus safely be used in if
s. To convert the result into a boolean, you could use not not string:match"9$"
.
Variable suffix: Rolling your own
Lua's standard library is very minimalistic; as such, you often need to roll your own functions even for basic things. There are two possible implementations for endswith
, one using pattern matching and another one using substrings; the latter approach is preferable because it's shorter, possibly faster (Lua uses a naive pattern matching engine) and doesn't have to take care of pattern escaping:
function string:endswith(suffix)
return self:sub(-#suffix) == suffix
end
Explanation: self:sub(-#suffix)
returns the last suffix length characters of self
, the first argument. This is compared against the suffix.
You can then call this function using the colon (:
) syntax:
str = "prefixsuffix"
assert(str:endswith"suffix")
assert(not str:endswith"prefix")