jawo
jawo

Reputation: 896

Sorting multidimensional table in Lua

The "how to sort a table in Lua" question isn't new, but the answers I found can't help me out, maybe you can.

I got this Table:

table       = {} -- some kind of database
table[1]    = {table.containing.table.with.even.more.tables.inside}
table[9]    = {table.containing.table.with.even.more.tables.inside}
table[13]   = {table.containing.table.with.even.more.tables.inside}
table[15]   = {table.containing.table.with.even.more.tables.inside}
table[45]   = {table.containing.table.with.even.more.tables.inside}
table[3254] = {table.containing.table.with.even.more.tables.inside}

Now I want to iterate through "table", check for an specified boolean it contains and if so, run a method with parameters from some subtabels.

for key, value in pairs(table) do
    print(key)
end

Is something like:

9    13   1   3254    45    15

As far as I know, that's because Lua iterates through hashvalues(right?).

My Idea was:

sorted_table = {} -- shall point to table, with sorted keys

for i = 0, #table do  -- from 0 to the last key of table (some write #table is the last key, some write it's the number of contained keys, I don't know. If you do, please tell me.)
    if table[i] then -- for runs every number from i to #table, if i is a key, bingo.
        table.insert(sorted_table,(table[i])) -- first key found -> sorted_table[1], second -> sorted_table[2]....
    end
end

for k,v in pairs(sorted_table) do
    print(key)
end

I got no error, it just jumps over the function and nothing happens. When I print #table, it prints 0. #table is in another file but it's not local but used at other location in the functionfile, so,.. this is weird.

EDIT Mh strange. I threw some debugs, #table is nil, but in a pairs(table) just under the code, everything works fine.

**SOLUTION-EDIT**

local sorted_table = {}
for k, v in pairs(original_table) do
    table.insert(sorted_table, k)
end
table.sort(sorted_table)
for k, v in ipairs(sorted_table) do
    print(original_table[v])
end

Upvotes: 1

Views: 2066

Answers (2)

Maze
Maze

Reputation: 156

A little try of explanation:

#table does not necessarily return the length of a table. A table element gets a default key if added in a table without a special key. These keys start from 1 and go up to n. If there is a gap between two keys, when you give your own key, #table will return the key right before that gap. Example:

t = {'one', 'two', 'three'} -- would be a table like 1 - one, 2 - two, 3 - three
print(#t) -- the last key -> 3, here it works
t2 = {'one', 'two', [4] = 'four'} -- would be a table like 1 - one, 2 - two, 4 - four
print(#t2) -- the last key without a gap -> 2, does not work

Same with pairs(table) and ipairs(table). ipairs iterates from key 1 to n without a gap, pairs iterates over all keys. That's why the solution works. You can set an own metamethod for the table (__len) to use # for the right length.

And remember that your table keys start at 1 by default. Hope it helped a bit to unterstand the problem here.

Upvotes: 3

jawo
jawo

Reputation: 896

SOLUTION

local sorted_table = {}
for k, v in pairs(original_table) do
    table.insert(sorted_table, k)
end
table.sort(sorted_table)
for k, v in ipairs(sorted_table) do
    print(original_table[v])
end

Upvotes: 2

Related Questions