Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Lua ➜ Using Lua table references.

Using Lua table references.

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Blainer   (191 posts)  Bio
Date Thu 26 Nov 2009 12:51 AM (UTC)
Message
If I have:
main_table = {a_key={"v"}, another_key={"val"}}
sorted_table = {}
sorted_table[1] = main_table.another_key
sorted_table[2] = main_table.a_key


Now if I want to delete all references to another_key is there a way to do that with out looping sorted_table.

I messed around with rawget and rawset. My understanding of the manual is if I change an object with rawset using the objects rawget name then all objects referencing that object will have that new value.

rawset (_G, rawget (main_table, "another_key"), nil)


This doesn't work at all.

Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #1 on Thu 26 Nov 2009 01:12 AM (UTC)

Amended on Thu 26 Nov 2009 01:13 AM (UTC) by WillFa

Message
Rawget and Rawset just bypass any metatables with __index and __newindex values.


master = {key="Hi"}
child = {}
setmetatable (child, {__index = master})

print (child.key) -- "Hi"
print (rawget(child,key)) -- nil



I don't know of a way to delete all references without a lot of loops.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #2 on Thu 26 Nov 2009 02:21 AM (UTC)
Message
This may not answer your question, but if you store in the sorted table the keys in the main table, and not the values, you can get back into the main table more easily. For example:


main_table = {
  key1 = "the",
  key2 = "brown",
  key3 = "fox",
  key4 = "jumped",
  key5 = "over",
  key6 = "a",
  key7 = "lazy",
  key8 = "dog",
  }

-- add to another table for sorting
sorted_table = {}

for k in pairs (main_table) do
  table.insert (sorted_table, k)
end -- for

-- sort based on the value of the key, not the key itself
table.sort (sorted_table, function (a, b) return main_table [a] < main_table [b] end )

-- show in sorted order
for k, v in ipairs (sorted_table) do
  print (main_table [v])
end -- for

-- I want to get rid of item 3 in the sorted table

k = sorted_table [3]  -- what key is it?

-- remove from sorted table
table.remove (sorted_table, 3)

-- remove from main table
main_table [k] = nil


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #3 on Thu 26 Nov 2009 02:23 AM (UTC)

Amended on Thu 26 Nov 2009 02:25 AM (UTC) by Nick Gammon

Message
Or, more simply, as table.remove returns the removed value:


-- remove from sorted table
k = table.remove (sorted_table, 3)  -- k is now the key

-- remove from main table
main_table [k] = nil



And I suppose you could combine those 2 lines:


main_table [table.remove (sorted_table, 3)] = nil


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Terry   USA  (87 posts)  Bio
Date Reply #4 on Thu 26 Nov 2009 02:32 AM (UTC)

Amended on Thu 26 Nov 2009 02:33 AM (UTC) by Terry

Message
I just did some fooling around with tables, and came up with this.

main_table = { }
  main_table.a_key = { "v" }
  main_table.another_key = { "val" }

print(main_table.a_key[1])
print(main_table.another_key[1])

table.remove(main_table.another_key)

print(main_table.a_key[1])
print(main_table.another_key[1])


The one absolutely major drawback, in my eyes, is the need to make each key a single-element array, instead of just a value.

For example:
main_table =
{
  ["a_key"] = "v",
  ["another_key"] = "val"
}

print(main_table["a_key"])
print(main_table["another_key"])

table.remove(main_table["another_key"])

print(main_table["a_key"])
print(main_table["another_key"])

*****
Run-time error
Immediate execution
[string "Immediate"]:10: bad argument #1 to 'remove' (table expected, got string)
stack traceback:
        [C]: in function 'remove'
        [string "Immediate"]:10: in main chunk


Also, since table.remove is literally looping through anyway, and just hiding it behind a rather painful method, I think it'd be much clearer to loop directly.


Edit: Of course nick would post while I answer :-D
Top

Posted by Blainer   (191 posts)  Bio
Date Reply #5 on Thu 26 Nov 2009 03:37 AM (UTC)
Message
Getting into main_table is not the problem it's finding the index in sorted_table I want to make faster.

main_table["unique_id_1"] = { id = "unique_id_1", desc = "a mean dog" }
main_table["unique_id_2"] = { id = "unique_id_2", desc = "a happy dog" }

sorted_table[1] = main_table.unique_id_2
sorted_table[2] = main_table.unique_id_1


main_table is keyed by the items unique id to enable easy look up when I have the item id. sorted_table
is in the order of these items from the MUD.

Now if I have the id I can get the item table easily from the main_table but when I need to remove
that item all together and keep the sorted_list in the order it came from the MUD I need to know the
table index of the item in sorted_table

At the moment I do this:
wanted_id = "unique_id_1"
main_table[wanted_id] = nil

for i,v in ipairs(sorted_table) do
  if wanted_id == v.id then
  	table.remove (sorted_table, i)
  	return
  end
end


This works but if you get 50 items to be removed at once and a large table it can get out of hand.
You might do 100 tests to find each item.
Top

Posted by Nick Gammon   Australia  (23,122 posts)  Bio   Forum Administrator
Date Reply #6 on Thu 26 Nov 2009 05:38 AM (UTC)
Message
Quote:

main_table["unique_id_1"] = { id = "unique_id_1", desc = "a mean dog" }
main_table["unique_id_2"] = { id = "unique_id_2", desc = "a happy dog" }

sorted_table[1] = main_table.unique_id_2
sorted_table[2] = main_table.unique_id_1


This isn't exactly what I suggested. I don't see how you can quickly get back to the main table here (you actually have a copy of the table entry, not the key itself).

To keep the key you would do:

Quote:

sorted_table[1] = "unique_id_2"
sorted_table[2] = "unique_id_1"


However your method might make it easier anyway. Since you have a copy of the *reference to* the table in the main table, then you can simply empty out the table item (don't replace it, that would cause a new table to be created).

So, for example:


t = main_table["unique_id_1"] 
for k in pairs (t) do
  t [k] = nil
end -- for


Now t is empty but not nil. Now you can set it to nil:


main_table["unique_id_1"]  = nil


That gets rid of it from the main table. Now later on you simply go through the sorted table and remove any table items that happen to have no elements. And before you do that you allow for (eg. for display purposes) that a table element with no items, is to be considered non-existent.

Another approach would be to store, in the main table, the key it belongs to in the sorted table.

Yet another approach is to resort the sorted table when required, eg. after you know additions or deletions have been made to the main table, and a sort not done afterwards.




- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Blainer   (191 posts)  Bio
Date Reply #7 on Thu 26 Nov 2009 07:53 AM (UTC)
Message
I never would have thought of that. Thank you.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


25,213 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.