GroupBy using a list of entries in Elm

What will the definition of the Elm function look like, which takes a list of records and performs a groupby operation (see example below)? Using the 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}]
+4
source share
3 answers

The following answer is kindly provided by @ 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))
+4
source

You can use Dict.Extra.groupByto perform the initial grouping, and then summarize ages by matching on a list and summing 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)
+4
source

, .

, , . .

import List
SumAgeByLast data = let
    sorted = List.sortBy .last data
    fst x = List.head x |> Maybe.withDefault {name= "_", last= "_", age= 0}
    agg lst p =if (fst lst).last==p.last then {name = "_", last = p.last ,age = (fst lst).age+p.age} else p::lst
  in
    List.foldl  agg [] sorted

p lst, , p::lst

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

, , .last .age

+2
source

Source: https://habr.com/ru/post/1692810/


All Articles