假设我有以下类型
type Key = String
type Score = Int
data Thing = Thing Key Score
如果我有这样的数组:
[Thing "a" 7, Thing "b" 5, Thing "a" 10]
是否有一种标准方法可以减少这种情况,以便我没有任何重复的密钥?如果两个键匹配,我想取得更好的分数
[Thing "b" 5, Thing "a" 10]
答案 0 :(得分:6)
一个非常简单的解决方案是使用Data.Map.fromListWith
,它将键值对列表转换为映射,给定一个函数将多个值与相同的键组合。
Prelude Data.Map> fromListWith max [("a", 7), ("b", 5), ("a", 10)]
fromList [("a",10),("b",5)]
请注意,这需要元组,因此必要时进行转换。此外,它不保留输入元素的顺序。运行时间为O(n log n)。
答案 1 :(得分:5)
首先,我们必须首先确定解决问题的方法以及实施难点。那么如果我们首先按Score
排序,然后只保留排序列表中第一次出现的Key
?这应该工作,让我们来看看haskell实现:
import Data.List
import Data.Function
type Key = String
type Score = Int
data Thing = Thing { key :: Key, score :: Score }
deriving (Show)
myNub = nubBy ((==) `on` key)
mySort = sortBy (compare `on` (negate . score))
selectFinest = myNub . mySort
现在我们尝试在ghci
:
Prelude> :load Test.hs
[1 of 1] Compiling Main ( Test.hs, interpreted )
Ok, modules loaded: Main.
*Main> selectFinest [Thing "a" 7, Thing "b" 5, Thing "a" 10]
[Thing {key = "a", score = 10},Thing {key = "b", score = 5}]
如果您不确定我在解决方案中使用的功能,请结帐hoogle。确实需要一些时间来学习如何使用on
和那些函数。
答案 2 :(得分:1)
我发布了一个O(n log n)解决方案,因为每个人看起来都很好O(n ^ 2)
consolidate :: (Ord a, Ord b) => [Thing a b] -> [Thing a b]
consolidate xs =
max_from_each_group (sortBy (compare `on` getKey) xs)
where
max_from_each_group [] = []
max_from_each_group (x:xs) =
let (same_key, rest) = span (\t -> x == getKey t) xs in
let group_max = maximumBy (compare `on` getValue) (x:same_key) in
group_max : max_from_each_group rest
答案 3 :(得分:0)
这是我的微弱尝试。肯定有一个更好的方式,但我不是 很多Haskell程序员。
import Data.List
type Key = String
type Score = Int
data Thing = Thing Key Score
deriving (Show, Ord)
instance Eq Thing where
(Thing k1 _) == (Thing k2 _) = k1 == k2
(Thing k1 _) /= (Thing k2 _) = k1 /= k2
thingSort :: [Thing] -> [Thing]
thingSort = Data.List.sortBy (flip compare)
ex = [Thing "a" 7, Thing "b" 5, Thing "a" 10]
filtered = nub (thingSort ex)