3

I have a lua table that contains 2 key pieces of data. I would like to sort the table in ascending order by the "num1" column, or if thats not possible, they by the key value in ascending order

Here's what I have so far:

local widgets = {}
widgets[1568] = {}
widgets[1568]["num1"] = 99999
widgets[1568]["val2"] = "NA"
widgets[246] = {}
widgets[246]["num1"] = 90885
widgets[246]["val2"] = "NA"
widgets[250] = {}
widgets[250]["num1"] = 95689
widgets[250]["val2"] = "NA"
widgets[251] = {}
widgets[251]["num1"] = 95326
widgets[251]["val2"] = "NA"
widgets[252] = {}
widgets[252]["num1"] = 95301
widgets[252]["val2"] = "NA"
widgets[256] = {}
widgets[256]["num1"] = 95303
widgets[256]["val2"] = "NA"

-- ATTEMPT TO SORT
--table.sort(widgets, function(a,b) return tonumber(a.num1.value) < tonumber(b.num1.value) end)
--table.sort(widgets, function(a,b) return tonumber(a.num1) < tonumber(b.num1) end)

--TRY SORTING BY ID:
table.sort(widgets, function(a,b) return tonumber(a) < tonumber(b) end)

for i, v in pairs(widgets) do
    print(v.num1)
end

Any suggestions would be appreciated. Right now, I'm reviewing Sort a Table[] in Lua to try to understand the "spairs" function. But that example is slightly different because I have a table within a table...

Thanks.

SOLUTION

In line with the answer below, I created a new table and added the records from the old table, one by one, using table insert like so:

local new_widgets = {}
for i, v in pairs(widgets) do
    table.insert(new_widgets, id=v.id, num1= v.num1, num2 = v.num2)
end

then I sorted new_wigets.

1
  • 4
    you will not be able to use table.sort for this, since the indices in your table do not start at 1 and run consecutively. internally, table.sort runs from 1 to #table, so it is not iterating the widgets. you'll have to roll your own sorting function and call it yourself. see the lua docs about table.sort to verify. your function will have to iterate the table with pairs. Commented Jun 11, 2014 at 13:29

1 Answer 1

5

Lua tables are hashtables. Their entries have no specific order.

You fake it by using consecutive numerical indices then iterating by incrementing a number (note: internally Lua actually will implement this as an array, but that's an implementation detail; conceptually, table entries have no specific order).

t[2] = "two"
t[3] = "three"
t[1] = "one"

for i=1,#t do print(t[i]) end

ipairs creates an iterator that does the same thing as this for loop.

So, if you want your data sorted, you need to put it in a table with consecutive numeric indices.

In your case, there's a lot of different ways you can do it. Here's one way to skin that cat:

Instead of this:

local widgets = {
    [246] = { num1 = 90885, val2 = "NA" }
    [250] = { num1 = 95689, val2 = "NA" }
    [251] = { num1 = 95326, val2 = "NA" }
    [252] = { num1 = 95301, val2 = "NA" }
    [256] = { num1 = 95303, val2 = "NA" }
}

You want this:

local widgets = {
    { id = 246, num1 = 90885, val2 = "NA" },
    { id = 250, num1 = 95689, val2 = "NA" },
    { id = 251, num1 = 95326, val2 = "NA" },
    { id = 252, num1 = 95301, val2 = "NA" },
    { id = 256, num1 = 95303, val2 = "NA" },
}

-- sort ascending by num1
table.sort(widgets, function(a,b) return a.num1 < b.num1 end)

for i, widget in ipairs(widgets) do
    print(widget.num1)
end

If you need the ability to then lookup a widget quickly by id, you can create a lookup table for that:

local widgetById = {}
for i,widget in pairs(widgets) do
    widgetById[widget.id] = widget
end
2
  • can you show me how to create the new table from the original? my original table is a result set from a database query which I can't change.
    – dot
    Commented Jun 11, 2014 at 17:28
  • I will try the table.insert
    – dot
    Commented Jun 11, 2014 at 18:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.