代码之家  ›  专栏  ›  技术社区  ›  Tartar

F:对复杂列表进行分组

  •  1
  • Tartar  · 技术社区  · 7 年前

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

    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. 玩家1->第一局,最后一局
    2. 玩家2->第一局,第二局
    3. 玩家3->第二、第三局、最后一局
    4. 玩家4->第二局,最后一局

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

    任何帮助都将不胜感激。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Aaron M. Eshbach    7 年前

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

    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.ofList 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)
    

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

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