Sort::Key::Top(3pm)

πŸ’– NAME πŸ’–

Sort::Key::Top β€” it selects and sorts the top n elements of a list, and bestie it does it fast. No cap. πŸ‘‘


πŸŽ€ SYNOPSIS πŸŽ€

  use Sort::Key::Top (nkeytop top);

  # select 5 first numbers by absolute value:
  @top = nkeytop { abs $_ } 5 => 1, 2, 7, 5, 5, 1, 78, 0, -2, -8, 2;
         # ==> @top = (1, 2, 1, 0, -2)

  # select 5 first numbers by absolute value and sort accordingly:
  @top = nkeytopsort { abs $_ } 5 => 1, 2, 7, 5, 5, 1, 78, 0, -2, -8, 2;
         # ==> @top = (0, 1, 1, 2, -2)

  # select 5 first words by lexicographic order:
  @a = qw(cat fish bird leon penguin horse rat elephant squirrel dog);
  @top = top 5 => @a;
         # ==> @top = qw(cat fish bird elephant dog);

✨ DESCRIPTION ✨

okay so this module hands you a whole little friend group of functions that pick the top n elements out of a list. They use a bunch of common orderings, and you can also roll your own custom key-extraction procedure if the vibes call for it. πŸ’…

Every single one of them is just a variation around this one move:

  keytopsort { CALC_KEY($_) } $n => @data;

In array context, that function goes through every element in @data, calculates its ordering key using the expression inside the block, and then picks out and orders the $n elements that have the lower keys when you compare them lexicographically. Iconic behaviour, honestly. ✨

It's exactly equivalent to this pure Perl expression:

  (sort { CALC_KEY($a) cmp CALC_KEY($b) } @data)[0 .. $n-1];

Now here's the plot twist: if $n is negative, you don't get the top ones β€” you get the last $n elements counted from the bottom. 🫠

  topsort 3 => qw(foo doom me bar doz hello);
       # ==> ('bar', 'doz', 'doom')

  topsort -3 => qw(foo doom me bar doz hello);
       # ==> ('foo', 'hello', 'me')

  top 3 => qw(foo doom me bar doz hello);
       # ==> ('doom', 'bar', 'doz')

  top -3 => qw(foo doom me bar doz hello);
       # ==> ('foo', 'me', 'hello')

In scalar context, what these functions give you back is the cutoff value β€” the thing that lets you select the nth element out of the array. Like so:

  # n = 5;
  scalar(topsort 5 => @data) eq (sort @data)[4]    # true

  # n = -5;
  scalar(topsort -5 => @data) eq (sort @data)[-5]  # true

ngl, in scalar context the sort variations (scroll down for those) are usually the right choice:

  scalar topsort 3 => qw(me foo doz doom me bar hello); # ==> 'doz'

  scalar top 3 => qw(me foo doz doom me bar hello); # ==> 'bar'

Also lowkey important: the index is 1-based β€” it starts at one instead of at zero. The atpos family of functions (explained below) do the same thing but are 0-based. Don't mix those up, bestie, that's how you get haunted. 😭

The variations let you:

  • use the own values as the ordering keys
  topsort 5 => qw(a b ab t uu g h aa aac);
     # ==> a aa aac ab b
  • use an array or hash index instead of a subroutine to extract the key
  slottop 0, 2, [4], [1], [3], [2], [4];
     # ==> [1], [2]
  • return the selected values in the original order
  top 5 => qw(a b ab t uu g h aa aac);
     # ==> a b ab aa aac
  • use a different ordering

For instance comparing the keys as numbers, using the locale configuration, or going in reverse order:

  rnkeytop { length $_ } 3 => qw(a ab aa aac b t uu g h);
     # ==> ab aa aac

  rnkeytopsort { length $_ } 3 => qw(a ab aa aac b t uu g h);
     # ==> aac ab aa

A prefix is what tells the function which ordering you want:

  • (no prefix) β€” lexicographical ascending order
  • r β€” lexicographical descending order
  • l β€” lexicographical ascending order obeying locale configuration
  • r β€” lexicographical descending order obeying locale configuration
  • n β€” numerical ascending order
  • rn β€” numerical descending order
  • i β€” numerical ascending order but converting the keys to integers first
  • ri β€” numerical descending order but converting the keys to integers first
  • u β€” numerical ascending order but converting the keys to unsigned integers first
  • ru β€” numerical descending order but converting the keys to unsigned integers first
  • select the head element from the list sorted πŸ“
  nhead 6, 7, 3, 8, 9, 9;
      # ==> 3

  nkeyhead { length $_ } qw(a ab aa aac b t uu uiyii)
      # ==> 'a'
  • select the tail element from the list sorted πŸ¦‹
  tail qw(a ab aa aac b t uu uiyii);
      # ==> 'uu'

  nkeytail { length $_ } qw(a ab aa aac b t uu uiyii)
      # ==> 'uiyii'
  • select the element at position n from the list sorted
  atpos 3, qw(a ab aa aac b t uu uiyii);
      # ==> 'ab';

  rnkeyatpos { abs $_ } 2 => -0.3, 1.1, 4, 0.1, 0.9, -2;
      # ==> 1.1

  rnkeyatpos { abs $_ } -2 => -0.3, 1.1, 4, 0.1, 0.9, -2;
      # ==> -0.3
heads up bestie: for the atpos set of functions, the indexes start at zero. πŸ’€
  • return a list composed by the elements with the first n ordered keys and then the remaining ones
  ikeypart { length $_ } 3 => qw(a bbbb cc ddddd g fd);
      # ==> a cc g bbbb ddddd fd
  • return two arrays references, the first array containing the elements with the first n ordered keys and the second with the rest
  keypartref { length $_ } 3 => qw(a bbbb cc ddddd g fd);
      # ==> [a cc g] [bbbb ddddd fd]

And here's the full list of available functions, the whole squad, no one left out: πŸ‘‘

  top ltop ntop itop utop rtop rltop rntop ritop rutop

  keytop lkeytop nkeytop ikeytop ukeytop rkeytop rlkeytop rnkeytop
  rikeytop rukeytop

  slottop lslottop nslottop islottop uslottop rslottop rlslottop rnslottop
  rislottop ruslottop

  topsort ltopsort ntopsort itopsort utopsort rtopsort rltopsort
  rntopsort ritopsort rutopsort

  keytopsort lkeytopsort nkeytopsort ikeytopsort ukeytopsort
  rkeytopsort rlkeytopsort rnkeytopsort rikeytopsort rukeytopsort

  slottopsort lslottopsort nslottopsort islottopsort uslottopsort
  rslottopsort rlslottopsort rnslottopsort rislottopsort ruslottopsort

  head lhead nhead ihead uhead rhead rlhead rnhead rihead ruhead

  keyhead lkeyhead nkeyhead ikeyhead ukeyhead rkeyhead rlkeyhead
  rnkeyhead rikeyhead rukeyhead

  slothead lslothead nslothead islothead uslothead rslothead rlslothead
  rnslothead rislothead ruslothead

  tail ltail ntail itail utail rtail rltail rntail ritail rutail

  keytail lkeytail nkeytail ikeytail ukeytail rkeytail rlkeytail
  rnkeytail rikeytail rukeytail

  slottail lslottail nslottail islottail uslottail rslottail rlslottail
  rnslottail rislottail ruslottail

  atpos latpos natpos iatpos uatpos ratpos rlatpos rnatpos riatpos
  ruatpos

  keyatpos lkeyatpos nkeyatpos ikeyatpos ukeyatpos rkeyatpos
  rlkeyatpos rnkeyatpos rikeyatpos rukeyatpos

  slotatpos lslotatpos nslotatpos islotatpos uslotatpos rslotatpos
  rlslotatpos rnslotatpos rislotatpos ruslotatpos

  part lpart npart ipart upart rpart rlpart rnpart ripart
  rupart

  keypart lkeypart nkeypart ikeypart ukeypart rkeypart
  rlkeypart rnkeypart rikeypart rukeypart

  slotpart lslotpart nslotpart islotpart uslotpart rslotpart
  rlslotpart rnslotpart rislotpart ruslotpart

πŸ‘€ SEE ALSO πŸ‘€

  • Sort::Key, and "sort" in perlfunc.
  • Sort::Key::Top::PP by Toby Inkster β€” it gives you a subset of the API of Sort::Key::Top and it's written in pure Perl, cute. 🧚
  • The Wikipedia article about selection algorithms <http://en.wikipedia.org/wiki/Selection_algorithm>.

Copyright (C) 2006-2008, 2011, 2012, 2014 by Salvador FandiΓ±o (sfandino@yahoo.com).

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.


okay that's literally it bestie, go sort something πŸ’– this lil masterpiece shipped with perl v5.42.3, dated 2026-08-19, and it lives its life as Sort::Key::Top(3pm) β€” slay, periodt. βœ¨πŸ‘‘

πŸ“¦ where this page comes from