按值对Data.Map进行排序并获取所有最大值

时间:2013-11-01 08:50:57

标签: haskell

我的Data.Map看起来像这样:

fromList [("eso",1),("mes",1),("ome",2),("som",2)]

我需要从此地图中获取值最大的键列表:

["ome","som"]

这是我的解决方案:

get_max_from_map m = map fst (filter is_biggest sorted)
    where sorted = List.sortBy (\(k1, v1) (k2, v2) -> v2 `compare` v1) $ Map.toList m
          max_v = snd $ head sorted
          is_biggest (key, value) = value == max_v

我将地图转换为列表,对它们进行排序,将第一个值作为最大值并过滤列表。

我只是想知道这项任务是否有更优化和美观的解决方案?

感谢。

3 个答案:

答案 0 :(得分:3)

这并不比原帖更简单,但它具有线性时,一次通过解决方案的优势(您的版本是O( n log n )因为它对列表进行了排序,到目前为止发布的其他答案是双遍解决方案。)

getMaxFromMap m = go [] Nothing (Map.toList m)
  where
    go ks _        []           = ks 
    go ks Nothing  ((k,v):rest) = go (k:ks) (Just v) rest
    go ks (Just u) ((k,v):rest)
        | v < u     = go ks     (Just u) rest
        | v > u     = go [k]    (Just v) rest
        | otherwise = go (k:ks) (Just v) rest

答案 1 :(得分:2)

您可以使用Data.Map monad中的Maybe功能处理此问题。

编辑:这是一个使用lens导入的工作版本。

import Control.Lens
import Data.Map (Map)
import qualified Data.Map as Map

getYourKeys :: Eq a => Map k a -> Maybe [k]
getYourKeys m = do
  maxValue <- maximumOf traverse m
  return . Map.keys . Map.filter (== maxValue) $ m

答案 2 :(得分:2)

您需要执行2项任务 - 找到最大值,过滤

get_max_from_lst xs = map fst $ filter ((== m) . snd) xs
    where m = maximum $ map snd xs

这是列表。

如果我们有Map,那么:

import Data.Map.Lazy as M

get_max_from_map xs = M.keys $ M.filter (== m) xs
    where m = maximum $ M.elems xs