我对这样的功能有疑问:
数据城市=城市{汽车::字符串,重量::整数,颜色::字符串}
-我有一个“城市”列表,我的函数必须列出一个元组列表,每个元组为(汽车,“重量之和”),因此,如果汽车等于,则汽车的重量为要添加,使像这样:
main> [(Porche,180),(Ferrari,400),(Opel,340)]
无法在输出列表上重复此车,因为必须增加其重量。
[我当时想做的事情是列出所有车型的清单,然后过滤重量并添加它们,制成清单,但我无法使其工作。
import Data.List
data City = City {car :: String, weight :: Int, color :: String} deriving (Show)
如果color
与City
相等无关,则可以将City
转换为元组。您可以使用map
执行此操作。
city2tup :: [City] -> [(String,Int)]
city2tup = map (\(City c w _) -> (c,w))
现在从sort
中查看功能groupBy
和Data.List
。在第一个元素上进行排序然后分组将在列表中收集相似的汽车。这样您将获得一个列表列表。现在,您只需要折叠每个子列表并添加相应的权重即可。
collect :: [City] -> [(String,Int)]
collect = map (foldl1 collectWeight) . groupBy ((==) `on` fst) . sort . city2tup
您仍然需要定义collectWeight
是什么,但这应该很容易。
import qualified Data.HashMap.Lazy as M
data City = City {car :: String, weight :: Int, color :: String}
ccw :: [City] -> [(String, Int)]
ccw [] = []
ccw (x:xs) = M.toList $ foldr addWeight (M.singleton (car x) (weight x)) xs
where
addWeight :: City -> M.HashMap String Int -> M.HashMap String Int
addWeight c r = case M.lookup (car c) r of
Nothing -> M.insert (car c) (weight c) r
Just x -> M.adjust (+ weight c) (car c) r
λ> ccw [City "Porsche" 180 "Black", City "Ferrari" 400 "Red", City "Opel" 340 "White", City "Porsche" 210 "Yellow"]
[("Opel",340),("Ferrari",400),("Porsche",390)]