Sorting a list of things in "(decide which number is)" order

Following up on this question, I realized I had one of my own.

I have a case where I want to list things to track in order of relevance. But I feel like I’m taking two steps when I should take one.

a sort-thing is a kind of thing. a sort-thing has a number called temp-sort-order.

p1 is a sort-thing.
p2 is a sort-thing.
p3 is a sort-thing.
p4 is a sort-thing.

to decide which number is sort-order-defined of (th - a sort-thing):
	if th is p1, decide on 1;
	if th is p2, decide on 2;
	if th is p3, decide on 3;
	if th is p4, decide on 4;
	decide on 0;

when play begins: [ this is just a check to make sure sord is sorted to p1, p2, p3, p4 ]
	let sord be { p3, p1, p4, p2 };
	say "[sord].";
	repeat with x running through sort-things:
		now temp-sort-order of x is sort-order-defined of x;
	sort sord in temp-sort-order order;
	say "[sord].";

I’m wondering if I’m missing a way to say sort sord in sort-order-defined order that compiles. But this doesn’t happen–at least, in 6L or 6G, it doesn’t. The solution I have is adequate, but if it could be more succinct, great!

Thanks!

1 Like

As mentioned in the post that you linked, it’s possible to sort a list by a property of the objects in it; see WWI 21.8 Sorting, reversing and rotating lists. You can’t sort on a computed property (though that would be nice), only a property that holds a value.

Is there a specific context in which you want to show things in a sorted order, or is this a generic effect that you’re trying to get?

1 Like

Let’s create it:

Step by step

First we create the I7 sort L in (phrase) order and sort L in reverse (phrase) order.
This is directly inspired by the existing code.

To sort (L - a list of objects) in/into (ph - phrase sort-thing -> number) order:
	(- LIST_OF_TY_SortBy({-lvalue-by-reference:L}, 1, {ph}); -).

To sort (L - a list of objects) in/into reverse (ph - phrase sort-thing -> number) order:
	(- LIST_OF_TY_SortBy({-lvalue-by-reference:L}, -1, {ph}); -).

Then, we need to provide LIST_OF_TY_SortBy :
This is a simplified version of LIST_OF_TY_Sort. All it does is to tell the sorting algorithm to use our ListCompareEntriesBy function.

[ LIST_OF_TY_SortBy list dir phrase no_items;
	BlkMakeMutable(list);
	no_items = BlkValueRead(list, LIST_LENGTH_F);
	SetSortDomain(ListSwapEntries, ListCompareEntriesBy);
	SortArray(list, phrase, dir, no_items, false, 0);
];

Then ListCompareEntriesBy:
This is a simplified version of ListCompareEntries . All it does is invoke the I7 phrase to get the computed value.

[ ListCompareEntriesBy list phrase i j;
	if (i==j) return 0;
	i = BlkValueRead(list, LIST_ITEM_BASE+i-1);
	j = BlkValueRead(list, LIST_ITEM_BASE+j-1);
	i = (phrase-->1)(i);
	j = (phrase-->1)(j);
	if (i > j) return 1;
	if (i < j) return -1;
	return 0;
];

Full example

a sort-thing is a kind of thing.

p1 is a sort-thing. 
p2 is a sort-thing. 
p3 is a sort-thing. 
p4 is a sort-thing. 

to decide which number is sort-order-defined of (th - a sort-thing) (this is simple sort):
	if th is p1, decide on 1;
	if th is p2, decide on 2;
	if th is p3, decide on 3;
	if th is p4, decide on 4;
	decide on 0;

to decide which number is sort-order-defined of (th - a sort-thing) (this is weird sort):
	if th is p1, decide on 13;
	if th is p2, decide on -5;
	if th is p3, decide on 22;
	if th is p4, decide on 4;
	decide on 0;

when play begins:
	let sord be { p3, p1, p4, p2 };
	say "[sord].";
	sort sord in simple sort order;
	say "[sord].";
	sort sord in reverse simple sort order;
	say "[sord].";
	sort sord in weird sort order;
	say "[sord].";
	
	
Lab is a room.

To sort (L - a list of objects) in/into (ph - phrase sort-thing -> number) order:
	(- LIST_OF_TY_SortBy({-lvalue-by-reference:L}, 1, {ph}); -).

To sort (L - a list of objects) in/into reverse (ph - phrase sort-thing -> number) order:
	(- LIST_OF_TY_SortBy({-lvalue-by-reference:L}, -1, {ph}); -).

Include (-

[ LIST_OF_TY_SortBy list dir phrase no_items;
	BlkMakeMutable(list);
	no_items = BlkValueRead(list, LIST_LENGTH_F);
	SetSortDomain(ListSwapEntries, ListCompareEntriesBy);
	SortArray(list, phrase, dir, no_items, false, 0);
];

[ ListCompareEntriesBy list phrase i j;
	if (i==j) return 0;
	i = BlkValueRead(list, LIST_ITEM_BASE+i-1);
	j = BlkValueRead(list, LIST_ITEM_BASE+j-1);
	i = (phrase-->1)(i);
	j = (phrase-->1)(j);
	if (i > j) return 1;
	if (i < j) return -1;
	return 0;
];

-)

5 Likes

I’d missed this originally, but thought I’d note that sorting lists and tables with custom phrases will be in the next Inform release. This is Inform evolution proposal 27.

The new phrases use the more conventional (from other languages) sorting API where the comparison function receives the two values to be compared. Except you can’t pass a whole table row to a phrase, so it passes the row numbers instead.

sort (list of values of kind K) with (phrase (K, K) → number)
sort (table name) with (phrase (table name, number, number) → number)

4 Likes