3

Does someone know a solution to save the key and the values to an table? My idea does not work because the length of the table is 0 and it should be 3.

local newstr = "3 = Hello, 67 = Hi, 2 = Bye"

a = {}
for k,v in newstr:gmatch "(%d+)%s*=%s*(%a+)" do 
    --print(k,v)
    a[k] = v
end

print(#a)

2 Answers 2

4

The output is correct.

run for k,v in pairs(a) do print(k,v) end to check the contents of your table.

The problem is the length operator which by default cannot be used to get the number of elements of any table but a sequence.

Please refer to the Lua manual: https://www.lua.org/manual/5.4/manual.html#3.4.7

When t is a sequence, #t returns its only border, which corresponds to the intuitive notion of the length of the sequence. When t is not a sequence, #t can return any of its borders. (The exact one depends on details of the internal representation of the table, which in turn can depend on how the table was populated and the memory addresses of its non-numeric keys.)

Only use the length operator if you know t is a sequence. That's a Lua table with integer indexes 1,..n without any gap.

You don't have a sequence as you're using non-numeric keys only. That's why #a is 0

The only safe way to get the number of elements of any table is to count them.

local count = 0
for i,v in pairs(a) do
  count = count + 1
end
Sign up to request clarification or add additional context in comments.

1 Comment

yeah i see. thanks
1

You can put @Piglet' code in the metatable of a as method __len that is used for table key counting with length operator #.

local newstr = "3 = Hello, 67 = Hi, 2 = Bye"

local a = setmetatable({},{__len = function(tab)
local count = 0
for i, v in pairs(tab) do
 count = count + 1
end
return count
end})

for k,v in newstr:gmatch "(%d+)%s*=%s*(%a+)" do 
    --print(k,v)
    a[k] = v
end

print(#a) -- puts out: 3

The output of #a with method __len even is correct if the table holds only a sequence.

You can check this online in the Lua Sandbox...
Lua Online CGI Sandbox ...with copy and paste.
Like i do.

2 Comments

imho it is not a good idea to suggest something like this as a general solution. you don't want to make it a beginner's habit to give every table a __len metamethod. I'm not even sure if you should confront any beginner who doesn't know the default behaviour of Lua's operators with metatables. for the few cases you need the number of table fields you can just call a function. I'd probably add it to the table library. also it is safe to assume that the OP already knows how to copy&paste and run Lua code as he complains about getting unexpected results. ;-) no offense
You put such a function in the table library. I put the table library functions one by one in the __index method of a table designed as table and after that i can change them without affecting the original table library. - It is so easy: newtable=setmetatable({},{__index={}}) for k,v in pairs(table) do getmetatable(newtable).__index[k]=v end newtable:insert('Hello World') print(newtable:concat())

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.