Page 1 of 2

Check if an element already exists in a table

Posted: Sun Nov 09, 2014 11:58 pm
by BruceTheGoose

Code: Select all

function Tower.getAllNear(self)
  local distance,nearest
  local shortestDistance = self.range
  for _,v in ipairs(Troop) do
    distance = self:getSquaredDistance(v)
    if distance <= shortestDistance then
      if self.targets[v] == nil then
        table.insert(self.targets,v)
      elseif self.targets[v] ~= nil then
        print("already exists!")
      end
    end
  end
end
I'm trying to check if an element already exists with in the table self.targets so that the same element doesn't keep getting inserted. However, the above code doesn't seem to get the job done. I do not receive the output and the same element continues to get inserted into the table.

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 12:17 am
by veethree
Something like this should work.

Code: Select all

if not self.targets[v] then
table.insert(self.targets,v)
end

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 12:47 am
by BruceTheGoose
Negative, I still get the same results.

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 3:01 am
by Azhukar
table.insert(self.targets,v) inserts value v at the beginning of your table.
"self.targets[v] == nil" checks whether any value exists at key v.
You mixed up values and keys.

I'm guessing you want your value to exist only once in your table. In that case you can simply use the value itself as a key for the table its in.

So your code would look something like this:

Code: Select all

if self.targets[v] == nil then
	self.targets[v] = true
else
	print("already exists!")
end
And you would iterate over self.targets like this:

Code: Select all

for v in pairs(self.targets) do
	print(v)
end

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 7:28 am
by Ortimh
It loops one time if you call the function, right? So why the same element inserted again? Does it loop again somewhere else? But what about restart the self.targets? I mean you remove all values within self.targets then refill it with nearest target. It may help.

Code: Select all

function Tower.getAllNear(self)
	self.targets = {}
	
	for index, value in ipairs(Troop) do
		if (self:getSquaredDistance(value) <= self.range) then
			table.insert(self.targets, value)
		end
	end
end
You shouldn't make a new variable if it only used one time like distance and shortestDistance. Also nearest made for nothing.

EDIT:
Maybe you should make a new local table then insert nearest targets which may help better.

Code: Select all

function Tower.getAllNear(self)
	local nearest = {}
	
	for index, troop in ipairs(Troop) do
		if (self:getSquaredDistance(troop) <= self.range) then
			table.insert(nearest, troop)
		end
	end
	
	return nearest
end
Azhukar, values for Troop that he loops maybe return a table so you can't index a table with a table.

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 7:53 am
by s-ol
Ortimh wrote:It loops one time if you call the function, right? So why the same element inserted again? Does it loop again somewhere else? But what about restart the self.targets? I mean you remove all values within self.targets then refill it with nearest target. It may help.

Code: Select all

function Tower.getAllNear(self)
	self.targets = {}
	
	for index, value in ipairs(Troop) do
		if (self:getSquaredDistance(value) <= self.range) then
			table.insert(self.targets, value)
		end
	end
end
You shouldn't make a new variable if it only used one time like distance and shortestDistance. Also nearest made for nothing.
maybe some of the variables are leftover from his actual code in the cleanup process. Nevertheless Azhukar is right, you mixed up values and keys. table.insert() is useless btw

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 1:46 pm
by Azhukar
Ortimh wrote:you can't index a table with a table.
Wrong.

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 2:07 pm
by s-ol
Azhukar wrote:
Ortimh wrote:you can't index a table with a table.
Wrong.
It does lead to problems when the table moves out of scope in the meantime though, so I suggest serializing to a string (table.join()) or keeping an index from a more permanent table if needed.

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 2:16 pm
by Azhukar
S0lll0s wrote:It does lead to problems when the table moves out of scope in the meantime though, so I suggest serializing to a string (table.join()) or keeping an index from a more permanent table if needed.
Wrong.

A table does not get garbage collected when it exists as a key in a non-weak key table. I'm guessing this is what you meant because talking of scope does not even make sense in this situation.

In case it is a weak-key table the keys that are references to garbage collected tables get removed on garbage collection.

Re: Check if an element already exists in a table

Posted: Mon Nov 10, 2014 2:29 pm
by s-ol
Azhukar wrote:
S0lll0s wrote:It does lead to problems when the table moves out of scope in the meantime though, so I suggest serializing to a string (table.join()) or keeping an index from a more permanent table if needed.
Wrong.

A table does not get garbage collected when it exists as a key in a non-weak key table. I'm guessing this is what you meant because talking of scope does not even make sense in this situation.

In case it is a weak-key table the keys that are references to garbage collected tables get removed on garbage collection.
Maybe the "out of scope" part is wrong, but I had this issue in a nother project, I had two different table "ids" (the memory address) but the same output on serialization.