NAME Sort::BySpec - Sort array (or create a list sorter) according to specification VERSION This document describes version 0.040 of Sort::BySpec (from Perl distribution Sort-BySpec), released on 2021-05-01. SYNOPSIS use Sort::BySpec qw(sort_by_spec cmp_by_spec); my $sorter = sort_by_spec(spec => [ # put odd numbers first, in ascending order qr/[13579]\z/ => sub { $_[0] <=> $_[1] }, # then put specific numbers here, in this order 4, 2, 42, # put even numbers last, in descending order sub { $_[0] % 2 == 0 } => sub { $_[1] <=> $_[0] }, ]); my @res = $sorter->(1..15, 42); # => (1,3,5,7,9,11,13,15, 4,2,42, 14,12,10,8,6) DESCRIPTION This package provides a more powerful alternative to Sort::ByExample. Unlike in `Sort::ByExample` where you only provide a single array of example, you can specify multiple examples as well as regex or matcher subroutine coupled with sort rules. With this, you can more precisely specify how elements of your list should be ordered. If your needs are not met by Sort::ByExample, you might want to consider this package. The downside is performance penalty, especially when your list is large. To sort using Sort::BySpec, you provide a "spec" which is an array of strings, regexes, or coderefs to match against elements of your list to be sorted. In the simplest form, the spec contains only a list of examples: my $sorter = sort_by_spec(spec => ["foo", "bar", "baz"]); # [1] and this is equivalent to Sort::ByExample: my $sorter = sbe(["foo", "bar", "baz"]); You can also specify regex to match elements. This is evaluated after strings, so this work: my $sorter = sort_by_spec(spec => [qr/o/, "foo", "bar", "baz", qr/a/]); my @list = ("foo", "food", "bar", "back", "baz", "fool", "boat"); my @res = $sorter->(@list); # => ("food","boat","fool", "foo","bar","baz", "back") Right after a regex, you can optionally specify a sort subroutine to tell how to sort elements matching that regex, for example: my $sorter = sort_by_spec(spec => [ qr/o/ => sub { $_[0] cmp $_[1] }, "foo", "bar", "baz", qr/a/ ]); # the same list @list above will now be sorted into: # => ("boat","food","fool", "foo","bar","baz", "back") Note that instead of $a and $b, you should use $_[0] and $_[1] respectively. This avoids the package scoping issue of $a and $b, making your sorter subroutine works everywhere without any special workaround. Finally, aside from strings and regexes, you can also specify a coderef matcher for more complex matching. Just like in the case of regex, right after the coderef you can optionally specify a sort subroutine (another coderef) to tell how to sort matching elements. For example: my $sorter = sort_by_spec(spec => [ # put odd numbers first, in ascending order sub { $_[0] % 2 } => sub { $_[0] <=> $_[1] }, # then put specific numbers here, in this order 4, 2, 42, # put even numbers last, in descending order sub { $_[0] % 2 == 0 } => sub { $_[1] <=> $_[0] }, ]); my @res = $sorter->(1..15, 42); # => (1,3,5,7,9,11,13,15, 4,2,42, 14,12,10,8,6) FUNCTIONS cmp_by_spec Usage: cmp_by_spec(%args) -> code Create a compare subroutine to be used in sort(). This function is not exported by default, but exportable. Arguments ('*' denotes required arguments): * reverse => *bool* If set to true, will reverse the sort order. * spec* => *array* * xform => *code* Code to return sort keys from data elements. This is just like "xform" in "Sort::ByExample". Return value: (code) sort_by_spec Usage: sort_by_spec(%args) -> array|code Sort array (or create a list sorter) according to specification. Examples: * Sort according to a sequence of scalars (like Sort::ByExample): sort_by_spec( spec => ["foo", "bar", "baz"], array => [1, 2, 3, "bar", "a", "b", "c", "baz"] ); Result: ["bar", "baz", 1, 2, 3, "a", "b", "c"] * Like previous example, but reversed: sort_by_spec( spec => ["foo", "bar", "baz"], array => [1, 2, 3, "bar", "a", "b", "c", "baz"], reverse => 1 ); Result: ["bar", "baz", 1, 2, 3, "a", "b", "c"] * Put integers first (in descending order), then a sequence of scalars, then others (in ascending order): sort_by_spec( spec => [ qr/\A\d+\z/, sub { $_[1] <=> $_[0] }, "foo", "bar", "baz", qr//, sub { $_[0] cmp $_[1] }, ], array => ["qux", "b", "a", "bar", "foo", 1, 10, 2] ); Result: [10, 2, 1, "foo", "bar", "a", "b", "qux"] This function is not exported by default, but exportable. Arguments ('*' denotes required arguments): * array => *array* * reverse => *bool* If set to true, will reverse the sort order. * spec* => *array* * xform => *code* Code to return sort keys from data elements. This is just like "xform" in "Sort::ByExample". Return value: Sorted array, or sort coderef (array|code) If array is specified, will returned the sorted array. If array is not specified in the argument, will return a sort subroutine that can be used to sort a list and return the sorted list. HOMEPAGE Please visit the project's homepage at . SOURCE Source repository is at . BUGS Please report any bugs or feature requests on the bugtracker website When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. SEE ALSO Sort::ByExample Bencher::Scenario::SortBySpec AUTHOR perlancar COPYRIGHT AND LICENSE This software is copyright (c) 2021, 2017, 2015 by perlancar@cpan.org. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.