Page 1 of 2

Indexing strings in Lua?

Posted: Sun Mar 20, 2011 10:41 am
by lesslucid
Hallo,

I'm just trying to work my way through some tutorials and there's something that I find quite confusing. I thought I'd make my own simpler version by using the indices of a string to create a table and write a function so that, eg ->

tablifyString("word") -- would produce the output { "w", "o", "r", "d" }

...but unlike in, say, python, where "word"[1] = "o", there doesn't seem to be a way in lua to grab a character out of a string according to its index.
Uh, unless there is, and I just couldn't find it?

Thanks v. much for any help or advice!

Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 10:58 am
by crow
I think it should be like so

Code: Select all

MyStringTable = tablifyString("word");
then to call your letter

Code: Select all

-- w
MyStringTable[1];
-- o
MyStringTable[2];
-- r
MyStringTable[3];
-- d
MyStringTable[4];

OldString = "";
for x =1, 4 do
OldString = OldString..MyStringTable[x];
end
love.graphics.print(OldString, 400, 300);


Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 11:07 am
by lesslucid
Thanks for your advice!

...I'm still a little lost, though. :(

If I had some way to index characters in a string, I could write a tablifyString function, like this:

Code: Select all

function tablifyString(str)
  local tempTable = {}
  for i, char in ipairs(str)
    temptable[i] = str[i]
  end
  return tempTable
end
Or something like that. But I can't, because for lua then str doesn't mean anything.

Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 11:22 am
by vrld
You can either use string.sub for indexing or string.gmatch to convert a string to a table of strings:

Code: Select all

str = "Hello, world"
print(str:sub(1,1), str:sub(2,2)) --> H    e
print(string.sub(str, 3,3)) --> l

function tablify(str)
    local tbl = {}
    for char in str:gmatch(".") do -- matches every character
        tbl[#tbl+1] = char
    end
    return tbl
end

Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 11:24 am
by crow
Maybe something like this?

Code: Select all

function tablifyString(str)
  count = string.len(str);
  local tempTable = {};
  for i = 1, string.len(s) do
    temptable[i] = string.sub(str, i, i);
  end
  return tempTable;
end
Edit:
  • Seems vrld got there before me lol

Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 11:36 am
by lesslucid
Ah, wonderful, thankyou both!

Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 6:39 pm
by Taehl
lesslucid wrote:...but unlike in, say, python, where "word"[1] = "o", there doesn't seem to be a way in lua to grab a character out of a string according to its index.
Uh, unless there is, and I just couldn't find it?
The Lua manual wrote: string.sub (s, i [, j])
Returns the substring of s that starts at i and continues until j; i and j can be negative. If j is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s, -i) returns a suffix of s with length i.

Re: Indexing strings in Lua?

Posted: Sun Mar 20, 2011 6:56 pm
by BlackBulletIV
You could do something complex like this:

Code: Select all

local smt = getmetatable("")
function smt.__index(str, key)
  if type(key) == 'number' then
    return string.sub(str, key, key)
  end
end
What's happening is I'm getting the metatable for strings (yes, there is one), and creating an __index function to handle the indexing of a non-existent key (such as a number). We can then turn this into a string.sub call, getting only one character. Example:

Code: Select all

('goo')[1] -- 'g'
Note that you can't do this:

Code: Select all

'goo'[1]
Lua doesn't support that syntax.

Re: Indexing strings in Lua?

Posted: Mon Mar 21, 2011 6:13 am
by lesslucid
Wow, I'm impressed that that's possible... thanks!

Re: Indexing strings in Lua?

Posted: Mon Mar 21, 2011 10:30 am
by BlackBulletIV
Yeah, I was pretty excited when I first discovered it. Here's a cool thing you can do:

Code: Select all

local smt = getmetatable("")
local stringMethods = {}

function stringMethods:print()
  print(self)
end

function stringMethods:sub(i, j)
  return string.sub(self, i, j)
end

function smt.__index(str, key)
  if type(key) == 'number' then
    return string.sub(str, key, key)
  elseif stringMethods[key] then
    return stringMethods[key]
  end
end
This would allow you to define methods callable on strings via this syntax:

Code: Select all

s = 'hello'
s:print() -- prints 'hello'
You might want to just make the __index function look at the string library, so can call all string functions from a string itself.