Reputation: 49
For example, if I have a list like this:
[("pizza", 4); ("milkshake", 2); ("chocolate", 2); ("pizza", 3); ("milkshake", 3); ("pizza", 4)]
and I want to sum all the second elements of the tuples while the first tuple is the same. How should I do it?
The output should be:
[("pizza", 11); ("milkshake", 5); ("chocolate, 2")]
Upvotes: 0
Views: 174
Reputation: 3029
You can used List.groupBy
to group the items according to the item name:
let items = [("pizza", 4); ("milkshake", 2); ("chocolate", 2); ("pizza", 3); ("milkshake", 3); ("pizza", 4)]
let grouped = List.groupBy fst items
// returns the following:
// [("pizza", [("pizza", 4); ("pizza", 3); ("pizza", 4)]);
// ("milkshake", [("milkshake", 2); ("milkshake", 3)]);
// ("chocolate", [("chocolate", 2)])]
This returns a list of tuples where the first entry is the item name (e.g. pizza) and the second entry is itself a list, containing all the original tuples which match that name.
Then you can map each sub-list to the sum of the second entries:
let summed = List.map (fun (name, entries) -> (name, entries |> List.sumBy snd)) grouped
// returns [("pizza", 11); ("milkshake", 5); ("chocolate", 2)] as expected
The documentation for the List module shows all the built in functions for working with lists.
Note that fst
and snd
are built-in functions which return the first and second elements of a two-element tuple respectively.
Once you're more familiar with F#, you might want to use the forward pipe operator |>
to do this more succinctly:
let summed =
items
|> List.groupBy fst
|> List.map (fun (name, entries) -> (name, entries |> List.sumBy snd))
Upvotes: 3