I want to delete all entries from a table, wich equals a given value.
Now, I got a pretty little problem one might to know, how to handle.
This is the Code:
function(list_to_search_in, compared_value, invert)
for k,v in pairs(list_to_search_in) do
if invert and v ~= compared_value then
table.remove(list_to_search_in, v)
if not invert and v == compared_value then
table.remove(list_to_search_in, v)
end
end
end
The Problem:
Let's say the table is { 1, 2, 3, 2 }. So when I'm iterating through that loop and come to the first match, it's removed from the table. This means the value and the key is deleted.
Now the key of the deleten value is assigned to the next value in line. But due the skript will check the value of the next key, this value (whichs kay has been just altered) will never be checked.
I thought, a simple
k = k - 1
after a remove would do the job, but it doesn't.
v = nil
would do great I think, but only if garbage-collector does not do his job in this very moment the pairs iterates to the next value.
Anyone has an idea? I would prefer an text-based hint to a finished syntax which solves the problem.
Don't use table.remove for this. It squeezes the "hole" out of array-like tables. That's not allowed during an iteration using pairs/next. Just set the value to nil.
If you need to squeeze holes out of the table then you can either create a new table and populate it with only the values you want to keep or do the removals during the first pass and then squeeze out holes in a second pass.
Also the order of item traversal when using pairs is not guaranteed in any way.
Related
if a table of N integer is present how to check if an element is repeating if present it shows message that table has repeating elements, if this is to be achieved in minimum time complexity
Hash table is the way to go (ie normal Lua table). Just loop over each integer and place it into the table as the key but first check if the key already exists. If it does then you have a repeat value. So something like:
values = { 1, 2, 3, 4, 5, 1 } -- input values
local htab = {}
for _, v in ipairs(values) do
if htab[v] then print('duplicate value: ' .. v)
else htab[v] = true end
end
With small integer values the table will use an array so will be O(1) to access. With larger and therefore sparser values the values will be in the hash table part of the table which can just be assumed to be O(1) as well. And since you have N values to insert this is O(N).
Getting faster than O(N) should not be possible since you have to visit each value in the list at least once.
Our task is create a table, and read values to the table using a loop. Print the values after the process is complete. - Create a table. - Read the number of values to be read to the table. - Read the values to the table using a loop. - Print the values in the table using another loop. for this we had written code as
local table = {}
for value in ipairs(table) do
io.read()
end
for value in ipairs(table) do
print(value)
end
not sure where we went wrong please help us. Our exception is
Input (stdin)
3
11
22
abc
Your Output (stdout)
~ no output ~
Expected Output
11
22
abc
Correct Code is
local table1 = {}
local x = io.read()
for line in io.lines() do
table.insert(table1, line)
end
for K, value in ipairs(table1) do
print(value)
end
Let's walk through this step-by-step.
Create a table.
Though the syntax is correct, table is a reserved pre-defined global name in Lua, and thus cannot should not be declared a variable name to avoid future issues. Instead, you'll need to want to use a different name. If you're insistent on using the word table, you'll have to distinguish it from the function global table. The easiest way to do this is change it to Table, as Lua is a case-sensitive language. Therefore, your table creation should look something like:
local Table = {}
Read values to the table using a loop.
Though Table is now established as a table, your for loop is only iterating through an empty table. It seems your goal is to iterate through the io.read() instead. But io.read() is probably not what you want here, though you can utilize a repeat loop if you wish to use io.read() via table.insert. However, repeat requires a condition that must be met for it to terminate, such as the length of the table reaching a certain amount (in your example, it would be until (#Table == 4)). Since this is a task you are given, I will not provide an example, but allow you to research this method and use it to your advantage.
Print the values after the process is complete.
You are on the right track with your printing loop. However, it must be noted that iterating through a table always returns two results, an index and a value. In your code, you would only return the index number, so your output would simply return:
1
2
3
4
If you are wanting the actual values, you'll need a placeholder for the index. Oftentimes, the placeholder for an unneeded variable in Lua is the underscore (_). Modify your for loop to account for the index, and you should be set.
Try modifying your code with the suggestions I've given and see if you can figure out how to achieve your end result.
Edited:
Thanks, Piglet, for corrections on the insight! I'd forgotten table itself wasn't a function, and wasn't reserved, but still bad form to use it as a variable name whether local or global. At least, it's how I was taught, but your comment is correct!
I got two tables, for example:
table1 = { element1, element2, element3, element4 }
table2 = { element1, element3 }
Table 2 refers to some elements of table1, but I don't know which exactly, nor I know their index.
Now, for an specific element I want to check if table2 does contains it or not and insert/remove it in the case.
First thing that jumped to my mind was:
table.remove/insert(table2, table1.elementX)
But due insert/remove does its lookup by index, this doesn't work.
Sure, I could iterate through the whole table until I find the element and remove it, respectively until Iteration is done without match and insert it.
But is there a more performant method to do this?
I do not want to fill table2 with empty fields for bringing the elements on matching indices.
To insert, it's quite straightforward:
table.insert(table1, table2[index])
Unfortunately, to remove, it's a bit more tricky:
local ids = {} -- table containing ids to remove
for i,v in ipair(table1) do
if v == table2[index] then
table.insert(ids, 1, i) -- "1" preprends the value
end
-- At this point, "ids" contains all the ids to remove in the reverse order
for k,v in pair(ids) do
table.remove(table1, v)
end
What happens here is:
An intermediate table is created, it only contains the ids of the table to remove, descending. For example: { 6, 3, 1} (if the value is present 3 times).
That intermediate table is used to update the main table, as you can't use the ids from a table you are updating in a loop (that's what the comments about "transversal" mean).
Note that those operations must be made from the end of the table, because removing an element will change the ids of the following ones.
First revert table2 with
table2reverse = {}
for k,v in pairs(table2) do table2reverse[v]=k end
Then do this:
for k,v in pairs(table1)do
if table2reverse[v] then
table1[k]=nil
end
Finally compact table1.
for k,v in pairs(table1)do
if v == table2[index] then
table.remove/insert(table1, k)
break
end
Of course this works, but I still hope there's a more performante solution.
Due in case of multiple 1000 entrys in table1 and multiple 100 entrys in table2, this is will lead to high cpu usage, wich I want to avoid. (programming a controller with only 200mhz)
I'm inserting the value of an variable to a table and want to make sure the action succeeded.
Therefore I want to return the value, but not by the var, but from the table.
Is there a more simple way as iterating trough the table again?
Some way to remember the key of the value in the table, while it's inserted?
function(value)
for _,v in pairs(theTable) do
if v == value then
return --(due the table already contains the value)
end
end
table.insert(theTable, value)
return -- table.[VALUE]
end
local ix = #theTable + 1
theTable[ix] = value
That's pretty much what table.insert is doing:
As a special (and frequent) case, if we call insert without a position, it inserts the element in the last position of the array (and, therefore, moves no elements)
As a sidenote, your function is pretty inefficient; you're doing an O(n) "contains" check, which could be made much better if you created an index of values.
In my Lua-powered game, I am trying to create an Explorer to see all the instances that have been created. I've created a function inside my DataModel "class" (as I like to call it) that will scan the children of an item, and put it neatly inside a table.
function DataModel.ObjectToTable(obj)
children = {}
for i,v in pairs(obj:GetChildren()) do
table.insert(children, DataModel.ObjectToTable(v))
end
print(obj.Name)
dmyself = {}
dmyself.Name = obj.Name
dmyself.Object = obj
dmyself.Children = children
print(#dmyself)
return dmyself
end
The issue is that, the print(#dmyself) is coming out as 0. But as you can see, I just set 3 things inside of it. What could cause such a thing to happen? Am I doing something obviously wrong?
The print(obj.Name) line is returning what it should. I am simply stuck on 'dmyself'.
# is the length of the array part of the Lua table; it only takes integer keys into account. More specifically,
The length of a table t is defined to be any integer index n such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, n can be zero. For a regular array, with non-nil values from 1 to a given n, its length is exactly that n, the index of its last value.
If you use pairs, you can see that your table is not empty. But since there's nothing in the array part of the table, it's length is zero.