1 | package Sort::Key;
|
---|
2 |
|
---|
3 | our $VERSION = '1.32';
|
---|
4 |
|
---|
5 | use 5.006;
|
---|
6 |
|
---|
7 | use strict;
|
---|
8 | use warnings;
|
---|
9 | use Carp;
|
---|
10 |
|
---|
11 | use Sort::Key::Types;
|
---|
12 |
|
---|
13 | require Exporter;
|
---|
14 |
|
---|
15 | our @ISA = qw(Exporter);
|
---|
16 | our @EXPORT_OK = qw( nsort nsort_inplace
|
---|
17 | isort isort_inplace
|
---|
18 | usort usort_inplace
|
---|
19 | rsort rsort_inplace
|
---|
20 | rnsort rnsort_inplace
|
---|
21 | risort risort_inplace
|
---|
22 | rusort rusort_inplace
|
---|
23 |
|
---|
24 | keysort keysort_inplace
|
---|
25 | rkeysort rkeysort_inplace
|
---|
26 | nkeysort nkeysort_inplace
|
---|
27 | rnkeysort rnkeysort_inplace
|
---|
28 | ikeysort ikeysort_inplace
|
---|
29 | rikeysort rikeysort_inplace
|
---|
30 | ukeysort ukeysort_inplace
|
---|
31 | rukeysort rukeysort_inplace
|
---|
32 |
|
---|
33 | multikeysorter multikeysorter_inplace);
|
---|
34 |
|
---|
35 | require XSLoader;
|
---|
36 | XSLoader::load('Sort::Key', $VERSION);
|
---|
37 |
|
---|
38 | sub multikeysorter {
|
---|
39 | if (ref $_[0] eq 'CODE') {
|
---|
40 | my $keygen = shift;
|
---|
41 | @_ or croak "too few keys";
|
---|
42 | my $ptypes = Sort::Key::Types::combine_types(@_);
|
---|
43 | my $sub = Sort::Key::Types::combine_sub($keygen, undef, @_);
|
---|
44 | return _multikeysorter($ptypes, $sub, undef);
|
---|
45 | }
|
---|
46 | else {
|
---|
47 | @_ or croak "too few keys";
|
---|
48 | my $ptypes = Sort::Key::Types::combine_types(@_);
|
---|
49 | my $sub = Sort::Key::Types::combine_sub('@_', undef, @_);
|
---|
50 | return _multikeysorter($ptypes, undef, $sub)
|
---|
51 | }
|
---|
52 | }
|
---|
53 |
|
---|
54 | sub multikeysorter_inplace {
|
---|
55 | if (ref $_[0] eq 'CODE') {
|
---|
56 | my $keygen = shift;
|
---|
57 | @_ or croak "too few keys";
|
---|
58 | my $ptypes = Sort::Key::Types::combine_types(@_);
|
---|
59 | my $sub = Sort::Key::Types::combine_sub($keygen, undef, @_);
|
---|
60 | return _multikeysorter_inplace($ptypes, $sub, undef);
|
---|
61 | }
|
---|
62 | else {
|
---|
63 | @_ or croak "too few keys";
|
---|
64 | my $ptypes = Sort::Key::Types::combine_types(@_);
|
---|
65 | my $sub = Sort::Key::Types::combine_sub('@_', undef, @_);
|
---|
66 | return _multikeysorter_inplace($ptypes, undef, $sub);
|
---|
67 | }
|
---|
68 | }
|
---|
69 |
|
---|
70 | sub register_type {
|
---|
71 | warn "Warning, Sort::Key API changed: register_type function has been moved to module Sort::Key::Types";
|
---|
72 | goto &Sort::Key::Types::register_type;
|
---|
73 | }
|
---|
74 |
|
---|
75 |
|
---|
76 | 1;
|
---|
77 |
|
---|
78 | __END__
|
---|
79 |
|
---|
80 | =head1 NAME
|
---|
81 |
|
---|
82 | Sort::Key - the fastest way to sort anything in Perl
|
---|
83 |
|
---|
84 | =head1 SYNOPSIS
|
---|
85 |
|
---|
86 | use Sort::Key qw(keysort nkeysort ikeysort);
|
---|
87 |
|
---|
88 | @by_name = keysort { "$_->{surname} $_->{name}" } @people;
|
---|
89 |
|
---|
90 | # sorting by a numeric key:
|
---|
91 | @by_age = nkeysort { $_->{age} } @people;
|
---|
92 |
|
---|
93 | # sorting by a numeric integer key:
|
---|
94 | @by_sons = ikeysort { $_->{sons} } @people;
|
---|
95 |
|
---|
96 | =head1 DESCRIPTION
|
---|
97 |
|
---|
98 | Sort::Key provides a set of functions to sort lists of values by some
|
---|
99 | calculated key value.
|
---|
100 |
|
---|
101 | It is faster (usually B<much faster>) and uses less memory than other
|
---|
102 | alternatives implemented around perl sort function (ST, GRT, etc.).
|
---|
103 |
|
---|
104 | Multikey sorting functionality is also provided via the companion
|
---|
105 | modules L<Sort::Key::Multi>, L<Sort::Key::Maker> and
|
---|
106 | L<Sort::Key::Register>.
|
---|
107 |
|
---|
108 | =head2 FUNCTIONS
|
---|
109 |
|
---|
110 | This module provides a large number of sorting subroutines but
|
---|
111 | they are all variations off the C<keysort> one:
|
---|
112 |
|
---|
113 | @sorted = keysort { CALC_KEY($_) } @data
|
---|
114 |
|
---|
115 | that is conceptually equivalent to
|
---|
116 |
|
---|
117 | @sorted = sort { CALC_KEY($a) cmp CALC_KEY($b) } @data
|
---|
118 |
|
---|
119 | and where C<CALC_KEY($_)> can be any expresion to extract the key
|
---|
120 | value from C<$_> (not only a subroutine call).
|
---|
121 |
|
---|
122 | For instance, some variations are C<nkeysort> that performs a numeric
|
---|
123 | comparison, C<rkeysort> that orders the data in descending order,
|
---|
124 | C<ikeysort> and C<ukeysort> that are optimized versions of C<nkeysort>
|
---|
125 | that can be used when the keys are integers or unsigned integers
|
---|
126 | respectively, etc.
|
---|
127 |
|
---|
128 | Also, inplace versions of the sorters are provided. For instance
|
---|
129 |
|
---|
130 | keysort_inplace { CALC_KEY($_) } @data
|
---|
131 |
|
---|
132 | that is equivalent to
|
---|
133 |
|
---|
134 | @data = keysort { CALC_KEY($_) } @data
|
---|
135 |
|
---|
136 | but being (a bit) faster and using less memory.
|
---|
137 |
|
---|
138 | The full list of subroutines that can be imported from this module
|
---|
139 | follows:
|
---|
140 |
|
---|
141 | =over 4
|
---|
142 |
|
---|
143 | =item keysort { CALC_KEY } @array
|
---|
144 |
|
---|
145 | returns the elements on C<@array> sorted by the key calculated
|
---|
146 | applying C<{ CALC_KEY }> to them.
|
---|
147 |
|
---|
148 | Inside C<{ CALC_KEY }>, the object is available as C<$_>.
|
---|
149 |
|
---|
150 | For example:
|
---|
151 |
|
---|
152 | @a=({name=>john, surname=>smith}, {name=>paul, surname=>belvedere});
|
---|
153 | @by_name=keysort {$_->{name}} @a;
|
---|
154 |
|
---|
155 | This function honours the C<use locale> pragma.
|
---|
156 |
|
---|
157 | =item nkeysort { CALC_KEY } @array
|
---|
158 |
|
---|
159 | similar to keysort but compares the keys numerically instead of
|
---|
160 | as strings.
|
---|
161 |
|
---|
162 | This function honours the C<use integer> pragma, i.e.:
|
---|
163 |
|
---|
164 | use integer;
|
---|
165 | my @s=(2.4, 2.0, 1.6, 1.2, 0.8);
|
---|
166 | my @ns = nkeysort { $_ } @s;
|
---|
167 | print "@ns\n"
|
---|
168 |
|
---|
169 | prints
|
---|
170 |
|
---|
171 | 0.8 1.6 1.2 2.4 2
|
---|
172 |
|
---|
173 | =item rnkeysort { CALC_KEY } @array
|
---|
174 |
|
---|
175 | works as nkeysort, comparing keys in reverse (or descending) numerical order.
|
---|
176 |
|
---|
177 | =item ikeysort { CALC_KEY } @array
|
---|
178 |
|
---|
179 | works as keysort but compares the keys as integers (32 bits or more,
|
---|
180 | no checking is performed for overflows).
|
---|
181 |
|
---|
182 | =item rikeysort { CALC_KEY } @array
|
---|
183 |
|
---|
184 | works as ikeysort, but in reverse (or descending) order.
|
---|
185 |
|
---|
186 | =item ukeysort { CALC_KEY } @array
|
---|
187 |
|
---|
188 | works as keysort but compares the keys as unsigned integers (32 bits
|
---|
189 | or more).
|
---|
190 |
|
---|
191 | For instance, it can be used to efficiently sort IP4 addresses:
|
---|
192 |
|
---|
193 | my @data = qw(1.2.3.4 4.3.2.1 11.1.111.1 222.12.1.34
|
---|
194 | 0.0.0.0 255.255.255.0) 127.0.0.1);
|
---|
195 |
|
---|
196 | my @sorted = ukeysort {
|
---|
197 | my @a = split /\./;
|
---|
198 | (((($a[0] << 8) + $a[1] << 8) + $a[2] << 8) + $a[3])
|
---|
199 | } @data;
|
---|
200 |
|
---|
201 | =item rukeysort { CALC_KEY } @array
|
---|
202 |
|
---|
203 | works as ukeysort, but in reverse (or descending) order.
|
---|
204 |
|
---|
205 | =item keysort_inplace { CALC_KEY } @array
|
---|
206 |
|
---|
207 | =item nkeysort_inplace { CALC_KEY } @array
|
---|
208 |
|
---|
209 | =item ikeysort_inplace { CALC_KEY } @array
|
---|
210 |
|
---|
211 | =item ukeysort_inplace { CALC_KEY } @array
|
---|
212 |
|
---|
213 | =item rkeysort_inplace { CALC_KEY } @array
|
---|
214 |
|
---|
215 | =item rnkeysort_inplace { CALC_KEY } @array
|
---|
216 |
|
---|
217 | =item rikeysort_inplace { CALC_KEY } @array
|
---|
218 |
|
---|
219 | =item rukeysort_inplace { CALC_KEY } @array
|
---|
220 |
|
---|
221 | work as the corresponding keysort functions but sorting the array
|
---|
222 | inplace.
|
---|
223 |
|
---|
224 | =item rsort @array
|
---|
225 |
|
---|
226 | =item nsort @array
|
---|
227 |
|
---|
228 | =item rnsort @array
|
---|
229 |
|
---|
230 | =item isort @array
|
---|
231 |
|
---|
232 | =item risort @array
|
---|
233 |
|
---|
234 | =item usort @array
|
---|
235 |
|
---|
236 | =item rusort @array
|
---|
237 |
|
---|
238 | =item rsort_inplace @array
|
---|
239 |
|
---|
240 | =item nsort_inplace @array
|
---|
241 |
|
---|
242 | =item rnsort_inplace @array
|
---|
243 |
|
---|
244 | =item isort_inplace @array
|
---|
245 |
|
---|
246 | =item risort_inplace @array
|
---|
247 |
|
---|
248 | =item usort_inplace @array
|
---|
249 |
|
---|
250 | =item rusort_inplace @array
|
---|
251 |
|
---|
252 | are simplified versions of its keysort cousins. They use the own
|
---|
253 | values as the sorting keys.
|
---|
254 |
|
---|
255 | For instance those constructions are equivalent:
|
---|
256 |
|
---|
257 | @sorted = nsort @foo;
|
---|
258 |
|
---|
259 | @sorted = nkeysort { $_ } @foo;
|
---|
260 |
|
---|
261 | @sorted = sort { $a <=> $b } @foo;
|
---|
262 |
|
---|
263 |
|
---|
264 | =item multikeysorter(@types)
|
---|
265 |
|
---|
266 | =item multikeysorter_inplace(@types)
|
---|
267 |
|
---|
268 | =item multikeysorter(\&genkeys, @types)
|
---|
269 |
|
---|
270 | =item multikeysorter_inplace(\&genkeys, @types)
|
---|
271 |
|
---|
272 | are the low level interface to the multikey sorting functionality
|
---|
273 | (normally, you should use L<Sort::Key::Maker> and
|
---|
274 | L<Sort::Key::Register> or L<Sort::Key::Multi> instead).
|
---|
275 |
|
---|
276 | They get a list of keys descriptions and return a reference to a
|
---|
277 | multikey sorting subroutine.
|
---|
278 |
|
---|
279 | Types accepted by default are:
|
---|
280 |
|
---|
281 | string, str, locale, loc, integer, int,
|
---|
282 | unsigned_integer, uint, number, num
|
---|
283 |
|
---|
284 | and support for additional types can be added via the L<register_type>
|
---|
285 | subroutine available from L<Sort::Key::Types> or the more
|
---|
286 | friendly interface available from L<Sort::Key::Register>.
|
---|
287 |
|
---|
288 | Types can be preceded by a minus sign to indicate descending order.
|
---|
289 |
|
---|
290 | If the first argument is a reference to a subroutine it is used as the
|
---|
291 | multikey extraction function. If not, the generated sorters
|
---|
292 | expect one as their first argument.
|
---|
293 |
|
---|
294 | Example:
|
---|
295 |
|
---|
296 | my $sorter1 = multikeysorter(sub {length $_, $_}, qw(int str));
|
---|
297 | my @sorted1 = &$sorter1(qw(foo fo o of oof));
|
---|
298 |
|
---|
299 | my $sorter2 = multikeysorter(qw(int str));
|
---|
300 | my @sorted2 = &$sorter2(sub {length $_, $_}, qw(foo fo o of oof));
|
---|
301 |
|
---|
302 |
|
---|
303 | =back
|
---|
304 |
|
---|
305 |
|
---|
306 | =head1 SEE ALSO
|
---|
307 |
|
---|
308 | perl L<sort> function, L<integer>, L<locale>.
|
---|
309 |
|
---|
310 | Companion modules L<Sort::Key::Multi>, L<Sort::Key::Register>,
|
---|
311 | L<Sort::Key::Maker> and L<Sort::Key::Natural>.
|
---|
312 |
|
---|
313 | L<Sort::Key::IPv4>, L<Sort::Key::DateTime> and L<Sort::Key::OID>
|
---|
314 | modules add support for additional datatypes to Sort::Key.
|
---|
315 |
|
---|
316 | L<Sort::Key::External> allows to sort huge lists that do not fit in
|
---|
317 | the available memory.
|
---|
318 |
|
---|
319 | Other interesting Perl sorting modules are L<Sort::Maker>,
|
---|
320 | L<Sort::Naturally> and L<Sort::External>.
|
---|
321 |
|
---|
322 | =head1 SUPPORT
|
---|
323 |
|
---|
324 | To report bugs, send me and email or use the CPAN bug tracking system
|
---|
325 | at L<http://rt.cpan.org>.
|
---|
326 |
|
---|
327 | =head2 Commercial support
|
---|
328 |
|
---|
329 | Commercial support, professional services and custom software
|
---|
330 | development around this module are available through my current
|
---|
331 | company. Drop me an email with a rough description of your
|
---|
332 | requirements and we will get back to you ASAP.
|
---|
333 |
|
---|
334 | =head2 My wishlist
|
---|
335 |
|
---|
336 | If you like this module and you're feeling generous, take a look at my
|
---|
337 | Amazon Wish List: L<http://amzn.com/w/1WU1P6IR5QZ42>
|
---|
338 |
|
---|
339 | =head1 COPYRIGHT AND LICENSE
|
---|
340 |
|
---|
341 | Copyright (C) 2005-2007, 2012 by Salvador FandiE<ntilde>o,
|
---|
342 | E<lt>[email protected]<gt>.
|
---|
343 |
|
---|
344 | This library is free software; you can redistribute it and/or modify
|
---|
345 | it under the same terms as Perl itself, either Perl version 5.8.4 or,
|
---|
346 | at your option, any later version of Perl 5 you may have available.
|
---|
347 |
|
---|
348 | =cut
|
---|