sorting
Thesort
filter lets you sort the output by various features you are interested in. We suggest using sort
where possible: it is easy to use,
there is no performance penalty, and it can yield greater insight into the output of a search.
More specifically, some filters can be sorted. This means two things:
- Such a filter has an associated count in any position that the filter matches.
- The games in the output pgn file are sorted in descending order by the maximum attained value of the count of that filter in that game
cql (input i.pgn) sort countsquares 4 16 [Qq]That is because the filter
countsquares 4 16 [Qq]will match a position with at least four queens. Whenever it does, the filter's count is that number of queens. The
sort
keyword
indicates that all games should be sorted by the maximum value which that filter attained on a position that it matches.
Counts associated with a filter
Some filters can be counted (sometimes we say it is countable or sortable). What is counted exactly depends on the nature of the particular filter. The documentation for the filter will say whether it is countable (not all filters are countable, and many are only countable if they use an explicit range.
Most filters that are countable are only countable when a range immediately follows the name of the filter.
For example, attack
is countable only when the word attack
is followed by a range:
attack (A _)is true in a position if a white piece attacks an empty square, but it is not countable. Thus,
sort attack (A _) ; ERRORwould give a syntax error, because the argument to sort is not countable.
However, when attack
is followed by a range, then the attack filter is countable.
It counts the number of attacks: the number of attacks by a white piece on an empty square.
sort attack 10 1000 (A _) ; LEGALwould sort the output by the maximum number of total attacks by a white piece on an empty square.
examples of counts
We discussed above that any count filter (a set filter followed by a range) can be counted. The filters in the following table are also all countable only when their name is followed by a range:countable filter: initial syntax | what is being counted |
---|---|
attack range | attacks |
countsquares range | squares in its argument |
square range | squares matching its arguments |
next range | length of the longest sequence of positions matching its arguments |
previous range | length of the longest sequence of positions matching its arguments |
next2 range | length of the longest sequence of positions matching its arguments, but only every other position starting with current position is counted |
previous2 range | length of the longest sequence of positions matching its arguments, but only every other position starting with current position is counted |
next* range | occurrences of its argument following current position |
previous* range | occurrences of its argument following current position |
power range | total material power of its argument |
powerdifference range | difference in material power between its first and second arguments |
movenumber range | move number of the current position |
year range | year of the current game |
elo range | elo of the specified player |
ray range | rays described by its arguments |
matchcount range | positions that are matched in a game |
Sorting
A game can be sorted by any countable filter. Just precede the filter either with wordsort
or with sort
and then a quoted documentation string.
For example:
sort attack 10 1000 (A _) ; sort by attacks on empty squares sort "Number of attacks" attack 10 1000 (A _) ; Same as above, but clearer outputThe second version will annotate the output games with the documentation string and value. (The first version will use a cryptic internal variable name instead of a descriptive annotation).
We suggest always using documentation strings with sort
. We find it makes the output easier to read and understand.
Multiple sorts
You can sort by multiple filters. When multiple filters are sorted, the output is sorted by each filter in the order the filters occur in the CQL file. For example, to following CQL file sorts by the maximum number of White pins in a position, and then by year. That is, if two game have the same number of pins, then they will be output together with the most recent first:cql(input i.pgn) sort "Number of pins" ray 1 10 attack (A a k) sort "Year" year 1 2020
Sorting by matchcount
To sort by the matchcount (the number of positions in the game that matched, assuming this number lies within the range of thematchcount,
preface the matchcount
CQL parameter
with sort
as in:
cql(input i.pgn sort matchcount 10 1000) check
This CQL code will find output games with at least 10 checks, sorted by the number of such checks.
sort matchcount
does not take a documentation string:
cql(input i.pgn sort "Matches" matchcount 10 1000); ERRORLikewise, matchcount cannot be sorted by minimum value:
sort min matchcount 1 10
is illegal.
See matchcount documentation for more information on matchcount
.
sorting by minimum in instead of the maximum
By default,sort
sorts games by the maximum attained value of its argument filter. However, if the keyword sort
is followed by the word min
, then games are sorted by the minimum attained value of its argument filter. In this case, the games are sorted in ascending order instead of descending order.
An example of this usage is in the file pinstalemate.cql. The line
sort min "material" power 1 1000 [Aa]will sort the games in order of increasing material. (Actually, in this example there is another sort by number of pins that comes first, so the games will be sorted first by descending order of the number pins, and then by ascending order by the material.
If you want to clarify that you want the default behavior of sorting by descending order of the maximum value, you can use sort max
instead of the lone keyword sort
. sort max
is just a synonym for sort
.
sorting relation filters
A relation filter cannot be sorted directly, but you can sort by maximum value of any LCA parameter (a parameter whose name begins with the characters "lca") by prefacing the name of the LCA parameter withsort
or with sort documentation-string
. In this case, the output is sorted by the
maximum value of that LCA parameter in any matching target.
See the relation sort documentation for more detail and examples.
Pitfalls in using sort
There are two common pitfalls to watch out for when using sort:- Anything used with sort must have a range even when it seems unnecessary. You will get a syntax
error if you try
sort movenumber
instead of saysort movenumber
without a range. - A more insidious error that can arise when using sort is when you sort a filter in a position that isn't actually matched.
For example, suppose you want to sort stalemates by the number of pieces in the stalemate:
cql(input i.pgn) ; WARNING... sort "Number Pieces" countsquares 1 32 [Aa] stalemate
The above CQL will output all games that end in stalemate, but will sort the games by the maximum number of pieces that arise at any time in that game. This of course is the same as the number of pieces in the initial position of the game, and is not what you want.To sort by the number of pieces in the stalemate itself you have to put the sort filter after the stalemate filter:
cql(input i.pgn) ; BETTER stalemate sort "Number Pieces" countsquares 1 32 [Aa]
Now the sort filter will only ever be evaluated in positions that are stalemates, so the sorting will be by the number of pieces in the stalemate position itself. Examples