F#:对复杂列表进行分组

时间:2018-09-25 19:44:23

标签: f# functional-programming

我正在尝试按照玩家列表的每个元素对列表进行分组

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

我想要得到的是找到哪个玩家加入了哪些游戏

(string * string list) list

例如根据该列表

  1. Player1->第一局,最后局
  2. Player2->第一局,第二局
  3. Player3->第二,第三场比赛,最后一场比赛
  4. Player4->第二局,最后一场

我尝试使用List.groupBy,但无法实现。我只是无法按玩家列表的每个元素对项目进行分组。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:3)

这是一个相当简单的解决方案:

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)

将列表列表分解成扁平结构,按玩家分组,然后转换为以玩家为键的地图,最后映射值以获得游戏名称。这将产生以下地图:

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"])]

编辑

要将内容保留在列表中,您可以仅使用List.map而不是Map.ofListMap.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)

这将以列表形式返回等效结果:

[("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"])]