# Can you sort a list by functions rather than properties?

I want to sort a deck of cards by suit, then by rank.

``````A card is a kind of thing. A card has a number called suit. A card has a number called rank.
AS is a card with suit 1 and rank 1. 2S is a card with suit 1 and rank 2. AC is a card with suit 2 and rank 1. 2C is a card with suit 2 and rank 2. [etc]

To decide what number is the position of (c - a card): decide on 13 * the suit of c + the rank of c.

Every turn:
let deck be the list of cards;
sort deck in position order;
...
``````

This doesnâ€™t work (obviously, thatâ€™s why Iâ€™m asking). I could I guess sort by rank, then by suit, but that relies on the sort being stable, which I donâ€™t know if it is, and isnâ€™t terribly clear or extensible anyways. Is there a way of doing what I want here?

I donâ€™t think thereâ€™s any way to do that with the built-in `sort` phrase, although you could probably do it if you implemented a sorting algorithm manually.

You could make `position` a property as well:

``````A card has a number called position.

When play begins:
repeat with c running through all cards:
now the position of c is 13 * the suit of c + the rank of c.
``````

Now the `sort deck in position order` will work.

If you have events that alter the suit/rank of a specific card then youâ€™ll have to update its position as well; they arenâ€™t automatically linked.

Another thing that might be worth considering (depending on your goal) is the approach shown in the Tilt 1 example, where cards are initially anonymous; the `reconstitute the deck` phrase effectively creates a sorted deck by reassigning the cards in a specific order (although it doesnâ€™t maintain that specific order).

Ungh, thatâ€™s not super great, but I suppose the â€śmake a quick extra property and populate it at the startâ€ť approach works. Thanks.

If you donâ€™t mind a text-based sort, another option would be to abuse the fact that text properties are actually routines:

``````A card has some text called position.
The position of a card is always "[suit of item described]-[rank of item described]".
``````

This still gives the cards an extra property but the value of this will be automatically calculated. You can use some other expressions (including `To say` expressions) to vary the ordering â€“ but note that as written, because this is a text sort without zero prefix, this is going to sort rank 10 right after rank 1, which is probably not what you want. Itâ€™s also almost certainly a bit slower than the other method.

1 Like

This doesnâ€™t work, Iâ€™m afraid. The position values arenâ€™t reduced to substituted form, so every card has the same position value, and the sort has no effect.

1 Like

It is.

The method of sorting is â€śstableâ€ť, that is, if two rows have the same value then they will stay the same way round in the sorted table, rather than being swapped over.

Ah, whoops. I tested that it compiled and it had the right `showme` output and the right sorted order â€“ but overlooked that the cards were already created in sorted order to start with.

Iâ€™m surprised itâ€™s not comparing the substituted values, though; thatâ€™s how most other things seem to treat text properties. It does work as expected if I explicitly assign simple text to each card.

To be fair, that particular reference only refers to table sorts; not list sorts. Hopefully those are stable too.

So to round that out, this does work to sort them in order, at least in a small test:

``````	sort deck in rank order;
sort deck in suit order;
``````

For the curious: current I7 does use the same algorithm for both table and list sorting; specifically, a tiled merge sort.