Ну, простым способом было бы использовать maximum
, чтобы найти самый большой элемент, а затем использовать findIndices
, чтобы найти каждое его вхождение. Что-то вроде:
largestIndices :: Ord a => [a] -> [Int]
largestIndices ls = findIndices (== maximum ls) ls
Однако, это не идеально, потому что maximum
является частичной функцией и будет ужасно раздражать, если ей дан пустой список. Вы можете легко избежать этого, добавив []
чехол:
largestIndices :: Ord a => [a] -> [Int]
largestIndices [] = []
largestIndices ls = findIndices (== maximum ls) ls
Настоящий трюк с этим ответом заключается в том, как я понял это. Я даже не знал о findIndices
до сих пор! Однако GHCi имеет аккуратную команду под названием :browse
.
Prelude> :browse Data.List
Здесь перечислены все функции, экспортируемые с помощью Data.List
. Используя это, я просто ищу сначала maximum
, а затем index
, чтобы увидеть, какие были варианты. И прямо к findIndex
было findIndecies
, что было идеально.
Наконец, я не стал бы беспокоиться об эффективности, если вы на самом деле не видите, что код работает медленно. GHC может - и выполняет - некоторые очень агрессивные оптимизации, потому что язык чистый, и он может сойти с рук. Поэтому единственное время, когда вам нужно беспокоиться о производительности, это когда - после компиляции с -O2 - вы видите, что это проблема.
РЕДАКТИРОВАТЬ: Если вы хотите найти индексы n
верхних элементов, вот простая идея: отсортируйте список по убыванию, возьмите первые n
уникальные элементы, получите их индексы с помощью elemIndices
и возьмите первые n
индексы из этого. Я надеюсь, что это относительно ясно.
Вот краткая версия моей идеи:
nLargestInices n ls = take n $ concatMap (`elemIndices` ls) nums
where nums = take n . reverse . nub $ sort ls