Sorting a table in a table alphabetically?

Hi,

just a quick question. I’m trying to sort a table, that is in another table alphabetically. Here is what my table looks like:

local saveData = {} saveData.names = {} saveData.dates = {} saveData.amounts = {} saveData.totalAmount = 0 saveData.income = {} saveData.colors = {}

So, I’d like to sort the names in saveData.names alphabetically AND because saveData.names[1], saveData.dates[1], … are linked to eachother, those should change aswell. So for example sorting this table:

saveData.names[1] = "Bram" saveData.names[2] = "Zeno" saveData.names[3] = "Lucas" saveData.amounts[1] = 20 saveData.amounts[2] = 5 saveData.amounts[3] = 10

should look like:

saveData.names[1] = "Bram" saveData.names[2] = "Lucas" saveData.names[3] = "Zeno" saveData.amounts[1] = 20 saveData.amounts[2] = 10 saveData.amounts[3] = 5

Note how when I change saveData.names[2], saveData.amounts[2] changes aswell.

 I’m puzzled on how to do this.

Any ideas?

Wouldn’t it be easier to store your data like this?

[lua]

local saveData = {}

saveData[1] = {name = “Bram”, amount = 20}

saveData[2] = {name = “Zemo”, amount = 5}

saveData[3] = {name = “Lucas”, amount = 10}

[/lua]

Then you can just do an ordinary sort on ‘name’.

Hi Nick,
It’d but I’ve been working for a few months on my project using the table from my first post. If I’d have the time to start all over again and re-write the code, I’d do it. But my goal was and is to get everything done by the beginning of my schoolyear which is around the corner :confused:

I agree with Nick, but you can solve this by temporarily coupling the data, sorting it, and decoupling it:

-- Note 1: This is a bad way to store data that is related. -- Note 2: It is better to tightly couple related data in a single table. -- local saveData = {} saveData.names = {} saveData.amounts = {} saveData.totalAmount = 0 saveData.names[1] = "Bram" saveData.names[2] = "Zeno" saveData.names[3] = "Lucas" saveData.amounts[1] = 20 saveData.amounts[2] = 5 saveData.amounts[3] = 10 -- Hack to sort 'uncoupled', but related data. -- -- WARNING: WILL ERROR OUT IF ALL TABLES DO NOT HAVE SAME NUMBER OF ENTRIES -- local function uncoupledSort( tbl, keys, sortKey ) -- Count entries local entries = #tbl[keys[1]] -- Temporarily Couple data local tmp = {} for i = 1, entries do local tmp2 = {} tmp[i] = tmp2 for k,v in pairs( keys ) do tmp2[v] = tbl[v][i] end end -- Sort local function compare(a,b) return tostring(a[sortKey]) \< tostring(b[sortKey]) end table.sort( tmp, compare ) -- Decouple data for i = 1, #tmp do for k,v in pairs(tmp[i]) do tbl[k][i] = v end end end uncoupledSort( saveData, { "names", "amounts" }, "names" )

Thanks Ed, this worked. But you guys are totally right by saying that I should just put some more time in the program. I’m probably going to run into other problems if I don’t change it now…

Thanks to both of you!

Sure thing.  Not looking to berate or shame.  Just don’t want you to struggle later with some weird issue.  Uncoupled (but related) data can be a total nightmare.

-Ed

Another approach would be to fill an array with the integers 1… #tbl[keys[1]] and sort that, using a compare closure that looks at saveData.names[i].

Afterward, use the indices to transfer everything into fresh arrays and then swap those out for the originals. I’ve used something along these lines every now and then (sometimes grouping things really is hard :)).

Since you won’t need the table again anyhow, yet another approach if you do go the couple-uncouple approach would be to stuff your packed entries into a priority queue, e.g. see the attachment here. (The thread itself is pretty interesting, too.) Then at the end just pull them off one by one and re-expand them. (This is basically the heapsort technique.)

Wouldn’t it be easier to store your data like this?

[lua]

local saveData = {}

saveData[1] = {name = “Bram”, amount = 20}

saveData[2] = {name = “Zemo”, amount = 5}

saveData[3] = {name = “Lucas”, amount = 10}

[/lua]

Then you can just do an ordinary sort on ‘name’.

Hi Nick,
It’d but I’ve been working for a few months on my project using the table from my first post. If I’d have the time to start all over again and re-write the code, I’d do it. But my goal was and is to get everything done by the beginning of my schoolyear which is around the corner :confused:

I agree with Nick, but you can solve this by temporarily coupling the data, sorting it, and decoupling it:

-- Note 1: This is a bad way to store data that is related. -- Note 2: It is better to tightly couple related data in a single table. -- local saveData = {} saveData.names = {} saveData.amounts = {} saveData.totalAmount = 0 saveData.names[1] = "Bram" saveData.names[2] = "Zeno" saveData.names[3] = "Lucas" saveData.amounts[1] = 20 saveData.amounts[2] = 5 saveData.amounts[3] = 10 -- Hack to sort 'uncoupled', but related data. -- -- WARNING: WILL ERROR OUT IF ALL TABLES DO NOT HAVE SAME NUMBER OF ENTRIES -- local function uncoupledSort( tbl, keys, sortKey ) -- Count entries local entries = #tbl[keys[1]] -- Temporarily Couple data local tmp = {} for i = 1, entries do local tmp2 = {} tmp[i] = tmp2 for k,v in pairs( keys ) do tmp2[v] = tbl[v][i] end end -- Sort local function compare(a,b) return tostring(a[sortKey]) \< tostring(b[sortKey]) end table.sort( tmp, compare ) -- Decouple data for i = 1, #tmp do for k,v in pairs(tmp[i]) do tbl[k][i] = v end end end uncoupledSort( saveData, { "names", "amounts" }, "names" )

Thanks Ed, this worked. But you guys are totally right by saying that I should just put some more time in the program. I’m probably going to run into other problems if I don’t change it now…

Thanks to both of you!

Sure thing.  Not looking to berate or shame.  Just don’t want you to struggle later with some weird issue.  Uncoupled (but related) data can be a total nightmare.

-Ed

Another approach would be to fill an array with the integers 1… #tbl[keys[1]] and sort that, using a compare closure that looks at saveData.names[i].

Afterward, use the indices to transfer everything into fresh arrays and then swap those out for the originals. I’ve used something along these lines every now and then (sometimes grouping things really is hard :)).

Since you won’t need the table again anyhow, yet another approach if you do go the couple-uncouple approach would be to stuff your packed entries into a priority queue, e.g. see the attachment here. (The thread itself is pretty interesting, too.) Then at the end just pull them off one by one and re-expand them. (This is basically the heapsort technique.)