Sub-sorting a table?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Sub-sorting a table?

Post by Jasoco »

Is it possible to sort a table by one parameter, then sub-sort it again by another parameter? And possibly again and again if needed?

Code: Select all

table.sort(t, function(a,b) return a>b end)
Doesn't seem to be an easy way that I can see. Maybe I'm missing something?
User avatar
ejmr
Party member
Posts: 302
Joined: Fri Jun 01, 2012 7:45 am
Location: South Carolina, U.S.A.
Contact:

Re: Sub-sorting a table?

Post by ejmr »

I am sorry if I am misunderstanding your question, but wouldn’t a series of

Code: Select all

table.sort()
calls work, with each using a more specific comparison function to sort by the sub-parameters you want?
ejmr :: Programming and Game-Dev Blog, GitHub
南無妙法蓮華經
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Sub-sorting a table?

Post by bartbes »

Actually, it's not that hard, just use an or in your sort function:

Code: Select all

Lua 5.2.1  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> test = {
>> {1, 1},
>> {1, 2},
>> {2, 1},
>> {2, 2}}
> table.sort(test, function(a, b) return a[1] > b[1] or a[2] > b[2] end)
> for i, v in ipairs(test) do print(v[1], v[2]) end
2	2
2	1
1	2
1	1
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Sub-sorting a table?

Post by kikito »

Jasoco wrote:Is it possible to sort a table by one parameter, then sub-sort it again by another parameter? And possibly again and again if needed?
I'm not understanding this. Can you give an example? i.e. an "unsorted" table vs the same table sorted the way you want.
When I write def I mean function.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Sub-sorting a table?

Post by micha »

kikito wrote:
Jasoco wrote:Is it possible to sort a table by one parameter, then sub-sort it again by another parameter? And possibly again and again if needed?
I'm not understanding this. Can you give an example? i.e. an "unsorted" table vs the same table sorted the way you want.
Jasoco wants to sort a table by a parameter. Then afterwards he wants to sort all entries, that are equal in one entry, with respect to another entry. This is also called Lexicographical order http://en.wikipedia.org/wiki/Lexicographic_order.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Sub-sorting a table?

Post by kikito »

micha wrote:Then afterwards he wants to sort all entries, that are equal in one entry, with respect to another entry. This is also called Lexicographical order http://en.wikipedia.org/wiki/Lexicographic_order.
Ow! Then you just write the sorting conditions in your sorting function. You can sort by 1,2 or any other properties.

Say that you have a list of people with ages and names, and you want it sorted by age first, and by name later.

Code: Select all

people = { { name='Bob', age=21 }, { name='Peter', age=18 }, { name='Andrew', age=18 } }
This will sort them by age only

Code: Select all

table.sort(people, function(a,b) return a.age < b.age end) -- Peter, Andrew, Bob
This will sort them by name only (undoing the previous sort):

Code: Select all

table.sort(people, function(a,b) return a.name < b.name end) -- Andrew, Bob, Peter
If you want to sort them out by name only when their age is the same. Well, add that to the sorting function!

Code: Select all

table.sort(people, function(a,b)
  if a.age == b.age then return a.name < b.name end
  return a.age < b.age
end) -- This will give you Andrew, Peter, Bob
When I write def I mean function.
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Sub-sorting a table?

Post by Inny »

You can also use the __lt metamethod to this end. But what everyone else said is how you want to go about this, i.e. define a comparison function that moves on to other properties when the primary properties are equal.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Sub-sorting a table?

Post by Robin »

Note that kikito's solution is better than bartbes'.

Why?

Suppose you want to compare {2, 2}, {3, 1}.
bartbes' version:

Code: Select all

table.sort(test, function(a, b) return a[1] > b[1] or a[2] > b[2] end)
-- return 2 > 3 or 2 > 1
-- return false or true
-- return true
kikito's version:
table.sort(test, function(a, b) if a[1] == b[1] then return a[2] > b[2] end return a[1] > b[1] end
-- if 2 == 3 then return 2 > 1 end return 2 > 3
-- if false then return true end return false
-- return false
You only want to look at the second condition if the first condition would compare equal.
Help us help you: attach a .love.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Sub-sorting a table?

Post by micha »

Lua does short-cut-evaluation. If you evaluate

Code: Select all

a or b
First a is evaluated and if it is true, then b is not evaluated. So in terms of speed, there should not be a large difference.

But I just discovered, that bartbes' and kikito's solution sort differently, as bartbes' solution does not check of equality (and I understand the original post such that equality has to be checked, otherwise the relation is not antisymmetric in the sense that it is possible to have a>b and b>a at the same time. If we try f({2,1},{1,2}) we get true and with f({1,2},{2,1}), too.).

Here is my proposed solution:

Code: Select all

table.sort(test, function(a, b) return a[1] > b[1] or (a[1] == b[1] and a[2] > b[2]) end)
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Sub-sorting a table?

Post by Robin »

That's... basically what I said.
Help us help you: attach a .love.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Roland Chastain and 199 guests