-1

我对这样的功能有疑问:

数据城市 = 城市 {汽车 :: 字符串,重量 :: Int,颜色 :: 字符串}

-我有一个“城市”列表,我的函数必须列出一个元组,每个元组是(汽车,“权重之和”),因此,如果汽车相等,则权重必须是添加,制作这样的东西:

main> [(Porche,180),(Ferrari,400),(Opel,340)]

汽车不能在输出列表中重复,因为必须添加它们的重量。

我正在考虑做一些事情,比如列出所有汽车类型的列表,然后过滤重量并添加它们,制作一个列表,但我无法让它发挥作用。

4

2 回答 2

5

我将指导您解决问题。了解如何得出解决方案比了解解决方案本身更好。

import Data.List
data City = City {car :: String, weight :: Int, color :: String} deriving (Show)

如果与相等color无关,则可以将其转换为元组。你可以用它来做到这一点。CityCitymap

city2tup :: [City] -> [(String,Int)]
city2tup = map (\(City c w _) -> (c,w))

现在看看 functionsortgroupByfrom Data.List。对第一个元素进行排序然后分组将在列表中收集相似的汽车。所以你会有一个列表列表。现在您只需要折叠每个子列表并添加相应的权重。

collect :: [City] -> [(String,Int)]
collect = map (foldl1 collectWeight) . groupBy ((==) `on` fst) . sort . city2tup

您仍然需要定义是什么collectWeight,但这应该很容易。

于 2012-12-29T06:07:48.960 回答
0

就性能而言,也许最好使用该Data.HashMap.Lazy软件包来完成这项工作。因此,您可以按以下方式进行;

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)]
于 2019-12-14T23:07:07.270 回答