12

It's easy enough to find the maximum value in a list in Perl 6:

> my @list = 1,4,9,7,3;
> say @list.max;
9

But if I want to find the index of the maximum entry, there doesn't seem to be an elegant way to do this.

> say (^@list).sort({ -@list[$_] })[0];
2
> say @list.pairs.sort(*.value).tail.key;
2
> say @list.first(@list.max, :k);
2

Those all work, but they're hardly elegant, let alone efficient.

Is there a better way to do this?

It'd be nice if max had :k, :v and :kv options, like for instance first has. Of course, there might not be a unique index (for instance, in the case of (1,4,9,7,9).max, but then again, there might not be a unique value either:

> dd (1, 2.0, 2.0e0, 2).max;
2.0
> say <the quick brown fox>.max(*.chars);
quick

max already retrieves the first maximum value, so it would be perfectly reasonable to return the first index with :k (or :kv).

Pat
  • 36,282
  • 18
  • 72
  • 87
mscha
  • 6,509
  • 3
  • 24
  • 40
  • I just realized that *the* index of the maximum value might not exist, for instance if the list is `1,4,9,7,3,9,1`. But still, a more elegant way to get *an* index would be welcome. – mscha Jan 09 '17 at 18:40
  • 1
    That's no different when returning the value. E.g. `dd (1, "2", 2).max(*.Int);` returns the Str value `"2"` instead of the Int value `2`, because it comes first. So `.max(:k)` returning the first matching index would be perfectly in line with existing behavior, and I'd consider the fact that the adverb is not supported here, an oversight. – smls Jan 10 '17 at 02:41
  • Good point. An even better example might be `dd(1, 2.0e0, 2.0, 2).max;`. – mscha Jan 10 '17 at 11:06
  • I added a final section about this to the question. – mscha Jan 10 '17 at 11:19

1 Answers1

15

You can use

@list.maxpairs

to get a list of all pairings of indices and maximal values or

@list.pairs.max(*.value).key

to get just a single index.

As far as I can see, both maxpairs and the ability to provide a transformation to max are still undocumented.

Christoph
  • 164,997
  • 36
  • 182
  • 240