Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GroupBy using list of records in Elm

Tags:

elm

What would an Elm function definition look like which takes a list of records, and perform a groupby operation (see example below)? Using a SQL analogy, I'm basically trying to achieve select last, sum(age) from table group by lastin Elm.

[{name= "John", last= "Smith", age= 10}
      ,{name="Jason", last= "Smith", age= 9}
      , {name="Jane", last ="White", age =5}]

 return [{last="Smith", age =19},
         {last ="White", age =5}]
like image 745
Jason O. Avatar asked Dec 18 '22 01:12

Jason O.


2 Answers

You could use Dict.Extra.groupBy to perform the initial grouping, then sum the ages by mapping over the list and summing the ages:

import Dict.Extra exposing (groupBy)

familySumAges : List Person -> List Family
familySumAges =
    groupBy .last
        >> Dict.map (\_ -> List.map .age >> List.sum)
        >> Dict.toList
        >> List.map (uncurry Family)
like image 72
Chad Gilbert Avatar answered Dec 24 '22 04:12

Chad Gilbert


The following answer courtesy of @holy-meekrob and @ilias from the Elm Slack channel. https://ellie-app.com/7tqY9w6gNa1/1

module Main exposing (..)

import Dict exposing (..)
import Html exposing (text)


type alias Person =
    { name : String
    , last : String
    , age : Int
    }


type alias Family =
    { last : String
    , age : Int
    }


people : List Person
people =
    [ { name = "John"
      , last = "Smith"
      , age = 10
      }
    , { name = "Jason"
      , last = "Smith"
      , age = 9
      }
    , { name = "Jane"
      , last = "White"
      , age = 5
      }
    ]


sumAges : Person -> Dict String Family -> Dict String Family
sumAges person families =

        Dict.update
            person.last
            (\family ->
                case family of
                    Nothing ->
                        Just { last = person.last, age = person.age }

                    Just fam ->
                        Just { last = person.last, age = fam.age + person.age }
            )
            families


main =
    text (toString (List.foldl sumAges Dict.empty people |> Dict.values))
like image 25
Jason O. Avatar answered Dec 24 '22 04:12

Jason O.