Question

I think that running this code you will get excactly what I mean. I want to register 5 names to a register(people). I loop 5 times and in each loop I have a variable newPerson which is supposed to save all information about a person and then be added to the people register. In this example only the names of the people are being registered for simplicity. The problem is that in the end all people turn to have the same name: "Petra". I playied a bit with this but can't get a reasonable reason for this behaviour. Help appreciated!

local people={}
local person={
    name="Johan",
    lastName="Seferidis",
    class="B"
}
local names={"Markus", "Eva", "Nikol", "Adam", "Petra"} --people to register


for i=1, 5 do --register 5 people
    local newPerson=person
    local name=names[i]
    for field=1, 3 do --for each field(name, lastname, class)
        if field==1 then newPerson["name"]=name end --register name
    end
    people[i]=newPerson
end

print("First person name: " ..people[1]["name"])
print("Second person name: "..people[2]["name"])
print("Third person name: " ..people[3]["name"])
Was it helpful?

Solution

The big thing at hand here is that Lua the variables "containing" a table in fact only contain a reference to a table. Copying variables containing tables does only copy the reference to that table, and thus represent the same table as in this example:

a={"x","y","z"}
b=a
b[2]="Q"
print(a[2]) -- returns Q and not y. Why is easily seen by doing:
print(a,b) -- returns table: 0xXXXXXX 0xXXXXXX indicating it's the same table

If you really want a copy of the table, you'll need to resort to something like http://lua-users.org/wiki/CopyTable

OTHER TIPS

Try this:

local people={}
local names={"Markus", "Eva", "Nikol", "Adam", "Petra"} --people to register

for i=1, 5 do
    people[i]={
        name=names[i],
        lastName="Seferidis",
        class="B"
        }
end

It looks like you are trying to use person as a prototype object. Here are some changes to the code that adds a new function to facilitate object prototyping.

object = {}
function object:new(o)
    -- use the table provided, or create a new table
    o = o or {}
    -- use this object as a prototype
    setmetatable(o, self)
    self.__index = self
    return o
end

local people={}
local person=object:new({name="Johan",lastName="Seferidis",class="B"})

local names={"Markus", "Eva", "Nikol", "Adam", "Petra"} --people to register

for i=1, 5 do --register 5 people
    local newPerson=person:new({["name"]=names[i]})
    people[i]=newPerson
end

print("First person name: " ..people[1].name.." "..people[1].lastName.." "..people[1].class)
-->First person name: Markus Seferidis B

print("Second person name: "..people[2].name.." "..people[2].lastName.." "..people[2].class)
-->Second person name: Eva Seferidis B

print("Third person name: " ..people[3].name.." "..people[3].lastName.." "..people[3].class)
-->Third person name: Nikol Seferidis B
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top