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

How to return the value of the first object in a table

Started by diamondpumpkin, 08 April 2017 - 05:01 PM
diamondpumpkin #1
Posted 08 April 2017 - 07:01 PM
I'm pretty confused, I'm using OpenCCSensors to detect an inventory, upon doing so I use the following:


os.loadAPI("ocs/apis/sensor")
local s = sensor.wrap("back")
local t = s.getTargets()
print(textutils.serialize(t)) -- Find out where the table lies
print("Table: " .. tostring(t[1]))

When I do this it prints:

{
  [ "0,0,0" ] = {
	RawName = "net.sensor",
	DamageValue = 3,
	Name = "Sensor",
	Position = {
		Y = 0,
		X = 0,
		Z = 0,
	},
	InventoryPercentFull = 1.5625,
	TotalSpace = 64,
	ItemCount = 1,
	},
}
Table: nil

However, when I replace 'print("Table: " .. tostring(t[1]))' with 'print("Table: " .. tostring(t["0,0,0"]))' it works as it should, and prints a table id. However, stated and shown in the table wiki (this part, if you're wondering) it shows I should be able to do this. Why can't I view the result with the position of the result in the table?
diamondpumpkin #2
Posted 08 April 2017 - 07:56 PM
I believe I understand now. I did some comparing to other tables I made myself, small ones. To give me a general idea. I believe when the system gets the targets it does something like


local table = {}
table["0,0,0"] = "stuff"
Therefore when I attempt to use 'print(table[1])' it gives nil because that has been replaced with something else. Correct me if I'm wrong. However, I can easily make a work around.
FuzzyLitchi #3
Posted 08 April 2017 - 11:24 PM
You can iterate through all values in a table by using pairs()


test_table = { ["0,0,0"] = "foo", ["0,1,1"] = "bar" }
for key, value in pairs(test_table) do
    print(key, value)
end
--output
--[0,0,0]  foo
--[0,1,1]  bar

if test_table had tables instead of the strings foo and bar, pairs() would not go into those tables.
pairs() only iterates through the top table.

if you just want the first* item of a table you can use

first = next(test_table)
I do not recommend this as it is unreliable under some conditions.

* tables may act in unexpected ways due to the fact that they do not have an specific order in the same way that other languages has them.
Exerro #4
Posted 09 April 2017 - 12:16 AM
To expand on what FuzzyLitchi said,

next(t) -- returns a the first key/value pair of the table, or nil if the table is empty
next(t, k) -- returns a subsequent key/value pair of the table, or nil if there are no further keys

The order in which keys are stored can't be relied on because of how they're dealt with internally.

If you need a reliable ordering, use numeric indexes and have a property in each value for what its key would've been, like this:

{
  [ 1 ] = {
        StringLocation = "0,0,0",
        RawName = "net.sensor",
        DamageValue = 3,
        Name = "Sensor",
        Position = {
                Y = 0,
                X = 0,
                Z = 0,
        },
        InventoryPercentFull = 1.5625,
        TotalSpace = 64,
        ItemCount = 1,
        },
}
although I see you already have a Position, so I guess you're relying on being able to look up (x..","..y..","..z).
diamondpumpkin #5
Posted 09 April 2017 - 03:48 AM
If you need a reliable ordering, use numeric indexes and have a property in each value for what its key would've been, like this:

{
  [ 1 ] = {
		StringLocation = "0,0,0",
		RawName = "net.sensor",
		DamageValue = 3,
		Name = "Sensor",
		Position = {
				Y = 0,
				X = 0,
				Z = 0,
		},
		InventoryPercentFull = 1.5625,
		TotalSpace = 64,
		ItemCount = 1,
		},
}
although I see you already have a Position, so I guess you're relying on being able to look up (x..","..y..","..z).

I would use numbers, which was my original question. Why couldn't I select the first object with table[1]. I didn't make the table, therefore I cannot change it's table property name. (Of course I can change it, I just can't set the original table to a number instead of cords) Like I said, I'm using OpenCCSensers which involves tables with lots of data, ones you don't create.
Edited on 09 April 2017 - 02:15 AM
valithor #6
Posted 09 April 2017 - 06:10 AM
If you need a reliable ordering, use numeric indexes and have a property in each value for what its key would've been, like this:

{
  [ 1 ] = {
		StringLocation = "0,0,0",
		RawName = "net.sensor",
		DamageValue = 3,
		Name = "Sensor",
		Position = {
				Y = 0,
				X = 0,
				Z = 0,
		},
		InventoryPercentFull = 1.5625,
		TotalSpace = 64,
		ItemCount = 1,
		},
}
although I see you already have a Position, so I guess you're relying on being able to look up (x..","..y..","..z).

I would use numbers, which was my original question. Why couldn't I select the first object with table[1]. I didn't make the table, therefore I cannot change it's table property name. (Of course I can change it, I just can't set the original table to a number instead of cords) Like I said, I'm using OpenCCSensers which involves tables with lots of data, ones you don't create.

You have to use the key that corresponds to the item you are wanting. Whenever you do table[1] that is not saying get the first item in the table. That is saying get the item in the table that corresponds to the key 1. Whenever you put items in a table without a key (As shown on the wiki in your example), they are numbered numerically starting at 1 corresponding to the spot they were put when you defined the table.

If there is only the one item in the table, then you can do as fuzzyLichi suggested and use next, otherwise you will need to either use the specific key you are wanting or loop through table and find the item you are wanting using pairs.
Edited on 09 April 2017 - 04:11 AM
diamondpumpkin #7
Posted 09 April 2017 - 02:53 PM
If you need a reliable ordering, use numeric indexes and have a property in each value for what its key would've been, like this:

{
  [ 1 ] = {
		StringLocation = "0,0,0",
		RawName = "net.sensor",
		DamageValue = 3,
		Name = "Sensor",
		Position = {
				Y = 0,
				X = 0,
				Z = 0,
		},
		InventoryPercentFull = 1.5625,
		TotalSpace = 64,
		ItemCount = 1,
		},
}
although I see you already have a Position, so I guess you're relying on being able to look up (x..","..y..","..z).

I would use numbers, which was my original question. Why couldn't I select the first object with table[1]. I didn't make the table, therefore I cannot change it's table property name. (Of course I can change it, I just can't set the original table to a number instead of cords) Like I said, I'm using OpenCCSensers which involves tables with lots of data, ones you don't create.

You have to use the key that corresponds to the item you are wanting. Whenever you do table[1] that is not saying get the first item in the table. That is saying get the item in the table that corresponds to the key 1. Whenever you put items in a table without a key (As shown on the wiki in your example), they are numbered numerically starting at 1 corresponding to the spot they were put when you defined the table.

If there is only the one item in the table, then you can do as fuzzyLichi suggested and use next, otherwise you will need to either use the specific key you are wanting or loop through table and find the item you are wanting using pairs.


I believe I understand now. I did some comparing to other tables I made myself, small ones. To give me a general idea. I believe when the system gets the targets it does something like


local table = {}
table["0,0,0"] = "stuff"
Therefore when I attempt to use 'print(table[1])' it gives nil because that has been replaced with something else. Correct me if I'm wrong. However, I can easily make a work around.

I do believe I already explained I figured this out.