tables

if i have a table:

``````table[1] = value1
table[2] = value2
table[3] = value3
``````

and i remove table[2],

``````table[2] = nil
``````

does it look like this:

``````table[1] = value1
table[2] = value3
``````

or like this:

``````table[1] = value1
table[3] = value3
``````

?

the actual question is, do the values change position after the position behind is deleted?

I don’t know but I just tried it using the online interpreter here: http://repl.it/

Setting table[2]=nil works as you suggest (i.e. table[3] contains value3) but doesn’t play nice (at least in my short tests) with ipairs() – the iterator stops after table[1] – nor with the table length function – print(#table) returns 1 – but I suggest you try it and see for yourself.

If you use table.remove(table,2) and iterate through the table with ipairs() you will get:

``````table[1] = value1
table[2] = value3
``````

`ipairs` starts at `1` and keeps going until `table[i]` evaluates to `nil`. So in this example, it stops at `1`. You still get everything with `pairs`, but not necessarily in the right order. If you want everything to stay sequential then you have to use `table.remove(table,2)` as that shifts everything down after removing the element (this will “cost” a little processing time, of course).

Oh good to know. Thanks.

Edit: is this the same reason that the table length operator (here #table) stops at 1 too?

Edit 2: Found the answer here:

``````If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).
``````

Section 2.5.5 http://www.lua.org/manual/5.1/manual.html

Yes - this is why the table length function stops, exactly so.

I find it helpful to simply think of an ‘array’, or a ‘hash’ - they’re both tables, but by using a given table exclusively as an array or a hash, the confusion dies down.

The array is simply a sparse array - if you want length, keep track of it yourself.

if it’s a hash, “ipairs” is simply invalid. Use “pairs”, and if you want it sorted… sort it, hashes are inherently unordered.

if you want an ordered hash, or anything more complex - make a class() and wrap up the details of your implementation.

Thanks. I must confess that I’m not familiar with the technical difference between an array and a hash. But I am learning…

(And here in Holland hash has rather other usage.)

those are perl words. Basically, an array is a group of items indexed by a number. A Hash is a group of items indexed by a key, which is usually a string. In other languages, they’ll call that a “map”.

key difference is the key - in an array, the key is an integer, usually starting with 0 (but 1 in lua!), and you don’t usually have holes (a sparse array). With a hash, the key is anything you want. A lua table is a hash or a map. A lua “array” is simply a table where you’ve promised yourself the keys will all be integers - consecutive integers if you want the #length function to work.

Although, to be precise, a lua table is both a hash and an array. It has an array part and a hash part and so it has the “best of both worlds” in that the array part is optimised for being an array and the hash part for being a hash. So `table[1]` and `table["1"]` are both legal in the same table but refer to different terms as the first is in the array part and the second in the hash.

Ah Mr. Bortels thank you. I’ve always been attracted to perl – at least from a distance (why? I don’t know exactly… but I suspect it has something to do with how monkish and arcane the code looks or the fact that it is often used to do the sort of things that interest me).

The thought that hash and array are perl terms will definitely help me remember the distinction you’ve made.

@Andrew ah, precision makes it all curiouser and curiouser.

Mmmm… Andrew, are you sure the array part is optimized for being an array? I suspect that’s not the case; an optimal array is a table of pointers, so lookup is fixed time. I suspect a lua table is always hashed key access. If that wasn’t the case, the length would be a simple size calculation, rather than the iteration thru the table that it is. The fact that you can mix integer and string keys tells me it’s not an optimal array… Where in a key table is “dog” as a key, and how would you handle a bucket collision? I’m pretty it’s simply a non-optimized table underneath.

I could look at the lua source to confirm, but I’m too damned lazy. (I’m sick today, at home in bed)

Okay, I don’t know about the “optimised” bit. But there are definitely two parts. I got my information from http://www.lua.org/gems/sample.pdf. Well worth reading.

I stand corrected! That’s an interesting document - it also mentions the causes behind some of the performance issues around string manipulations in a loop. I may need to buy the book.

So - Andrew’s right; if you keep your keys to integers 0-n, and you go consecutively, you should have array-like (not hash-like) performance. A pleasant surprise!

I don’t mind being wrong, especially when it turns out I was pessimistic.

Ive tried it Out, in an app called"luabox" and there the output was:

``````table[1] = value1
table[2] = Nil
table[3] = value3
``````

Yipiiieee

@Maxiking16 Glad you got what you wanted. And thanks for asking the question… I’ve definitely learned something because you did.