This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
jag's profile picture

Table Manipulation

Started by jag, 18 November 2013 - 03:15 PM
jag #1
Posted 18 November 2013 - 04:15 PM
Example:
I got a table like so:

local values = {
	[1] = "one",
	[2] = "two",
	[3] = "tree",
	[4] = "four",
}
And I want to insert a value (not with table.insert()) in a specific location.

local function add(table,index,element)
	for i = #table,index,-1 do
		table[i+1] = table[i]
	end
	table[index] = element
	return table
end

Basically push the values at the position entered, ex:

add(values,3,"two point five")
which ends up with a table like so

values = {
	[1] = "one",
	[2] = "two",
	[3] = "two point five",
	[4] = "tree",
	[5] = "four"
}

Is the example function I provided good? Or can it be done a much more elegant and compact way?
This function does not work if the table got gaps.

I need a similar function to do the same but reverse, remove a index and pull the elements after towards it, so to speak.

Ex:

local function remove(table,index)
	local max = #table
	for i = index+1,max do
		table[i-1] = table[i]
	end
	table[max] = nil
	return table
end

Which ends up with a table that looks like

remove(values,3)
values = {
	[1] = "one",
	[2] = "two",
	[5] = "four"
}

Also while testing these functions I noticed that they don't only change the internal values from the arguments but also the initial table, the same way the table.sort() does. Why is that and how do I fix that?
Edited on 18 November 2013 - 03:16 PM
Bomb Bloke #2
Posted 18 November 2013 - 06:00 PM
This function does not work if the table got gaps.
"#tableName" returns the highest index in the table before encountering a nil value. "table.getn(tableName)" always returns the highest index in the table.

I don't see a point to the use of the "max" variable in your second function, but it otherwise looks fine to me. Except that there's no need to return the table, because:

Also while testing these functions I noticed that they don't only change the internal values from the arguments but also the initial table, the same way the table.sort() does. Why is that and how do I fix that?
When you set a variable up as a table, it doesn't actually become the table… it becomes a pointer to the table. If you set another variable to be the same as the first, then you've got two pointers… which lead to the same table.

The only real "fix" is to manually create a new table, and copy all the indexes from the first to the second, one at a time. You've then got two different tables that you can manipulate independantly of each other.

But unless you specifically want to keep a copy of the old table, you may as well just roll with it.
Edited on 18 November 2013 - 05:01 PM
theoriginalbit #3
Posted 18 November 2013 - 07:00 PM
A problem that you do have is you're naming the table variable table, this is a naming conflict with the table API.

"#tableName" returns the highest index in the table before encountering a nil value. "table.getn(tableName)" always returns the highest index in the table.
I think you mean table.maxn returns the highest index. table.getn is the same as #

I don't see a point to the use of the "max" variable in your second function, but it otherwise looks fine to me. Except that there's no need to return the table, because:
Removes the need to run #table again.
Edited on 18 November 2013 - 06:00 PM
jag #4
Posted 19 November 2013 - 03:13 AM
–snip–
–snip–

Conclusions:
  • functions looks good, not much can get improved
  • use table.maxn instead of # or table.getn
  • dont need to return table, just edit via table pointer
New functions:

local function add(tbl,index,element)
	for i = table.maxn(tbl),index,-1 do
		tbl[i+1] = tbl[i]
	end
	tbl[index] = element
end

local function remove(tbl,index)
	local max = table.maxn(tbl)
	for i = index+1,max do
		tbl[i-1] = tbl[i]
	end
	tbl[max] = nil
end

Looks good?
Edited on 19 November 2013 - 02:19 AM
jag #5
Posted 19 November 2013 - 03:22 AM
Testing the code:

addtest
Spoiler

local values = {
	[1] = "one",
	[2] = "two",
	[3] = "tree",
	[4] = "four",
}
local function add(tbl,index,element)
	for i = table.maxn(tbl),index,-1 do
		tbl[i+1] = tbl[i]
	end
	tbl[index] = element
end
add(values,3,"two point five")
print("Table with added element")
for index,value in pairs(values) do
	print(index.."="..tostring(value))
end

removetest
Spoiler

local values = {
	[1] = "one",
	[2] = "two",
	[3] = "tree",
	[4] = "four",
}
local function remove(tbl,index)
	local max = table.maxn(tbl)
	for i = index+1,max do
		tbl[i-1] = tbl[i]
	end
	tbl[max] = nil
end
remove(values,3)
print("Table with removed element")
for index,value in pairs(values) do
	print(index.."="..tostring(value))
end

results



Thank you both very much, 1+ on the reputation counter for ya :)/>
Edited on 19 November 2013 - 02:32 AM
Bomb Bloke #6
Posted 19 November 2013 - 07:28 AM
I think you mean table.maxn returns the highest index. table.getn is the same as #
Ah. Really? I always thought it was a bit ambiguous as to what "getn" was supposed to mean. "maxn" is clearly more suited to the purpose, even if getn is NOT the same as # within the versions of ComputerCraft I've used (the highest I've gone thus far being 1.53).

I see it behaves as you're thinking on repl.it, though if I run that same script in CC I get a different output:

2,6

1,3
theoriginalbit #7
Posted 19 November 2013 - 07:36 AM
-snip-
Here you go.
Bomb Bloke #8
Posted 19 November 2013 - 08:02 AM
Yep, CC matches that behaviour. :)/>