Reputation: 5452
I am trying to group the list by each element of player list
let playersScore= [
(["Player 1";"Player 2";], "First Game");
(["Player 2";"Player 3";"Player 4";], "Second Game");
(["Player 3"], "Third Game");
(["Player 1";"Player 2";"Player 3";"Player 4";], "Last Game")] : scorePlayerItem list
What I want to get is to find which player has joined to which games as
(string * string list) list
For example according to that list
I tried to use List.groupBy
but could not achive this. I just could not manage to group items by each element of player list.
Any help would be appreciated.
Upvotes: 2
Views: 139
Reputation: 6510
Here's a fairly simple solution:
let groups =
playersScore
|> List.collect (fun (players, game) -> players |> List.map (fun player -> player, game))
|> List.groupBy (fun (player, _) -> player)
|> Map.ofList
|> Map.map (fun _ games -> games |> List.map snd)
Break out the list of lists into a flat structure, group them by player, then convert to a map with the player as the key, and finally map the values to get just the name of the game. This produces the following map:
map
[("Player 1", ["First Game"; "Last Game"]);
("Player 2", ["First Game"; "Second Game"; "Last Game"]);
("Player 3", ["Second Game"; "Third Game"; "Last Game"]);
("Player 4", ["Second Game"; "Last Game"])]
EDIT
To keep things as a list, you can just use List.map
instead of Map.ofList
and Map.map
:
let groups =
playersScore
|> List.collect (fun (players, game) -> players |> List.map (fun player -> player, game))
|> List.groupBy (fun (player, _) -> player)
|> List.map (fun (player, games) -> player, games |> List.map snd)
This returns the equivalent result as a list:
[("Player 1", ["First Game"; "Last Game"]);
("Player 2", ["First Game"; "Second Game"; "Last Game"]);
("Player 3", ["Second Game"; "Third Game"; "Last Game"]);
("Player 4", ["Second Game"; "Last Game"])]
Upvotes: 3