Reputation: 101
I want to combine my list but I need to pass in a dummy initial value which is why I want to use 'foldr'.
My current list is:
[[(1, "Bob J", 4.0)],[(1, "Bill J", 2.5),(2,"Bill J", 2.7)]]
I want to combine the list based on their names but I also need to do arithmetic when I am combining the number.
My current code is:
grp xs = foldr combine xs
where
combine
(x,_,y)
(totalX,_,totalY)
= (totalX+x,_,totalY+fromIntegral x *y)
This returns an error. I want totalX and totalY to initially be zero so it doesn't mess with the calculations. How do I do this?
Edit: I want my output to be in the same format so I want:
[(1,"Bob J", 4.0],(3,"Bill J", 2.6)]
Upvotes: 0
Views: 1356
Reputation: 8103
First I would flatten your list (use concat
), then accumulate the values into a Map
recursively. While accumulating, I would ensure that you upsert existing values with addition (this is what the add
function does).
module Main where
import Data.List
import qualified Data.Map as M
main = print $ makeMap vals
makeMap :: (Ord k, Num a, Num b) => [(a, k, b)] -> M.Map k (a, b)
makeMap = foldl' go mempty
where
go m (x,name,y) = M.insertWith add name (x,y) m
add (a,b) (c,d) = (a+c,b+d)
vals = concat [[(1, "Bob J", 4.0)],[(1, "Bill J", 2.5),(2,"Bill J", 2.7)]]
Result is
λ> main
fromList [("Bill J",(3,5.2)),("Bob J",(1,4.0))]
Upvotes: 1