Если задан список (a * b), вернуть список (a * b)

Возможно, это забавное название, но у меня проблема со следующим:

Дан список типов (a * b) listЯ хочу создать новый список с типом (a * b list) list, Пример:

Данный список let testList = [(1,"c");(2,"a");(1,"b")]моя функция должна вернуться [(1, ["c";"b"]; (2, ["a"])],

У меня есть следующее, но я немного застрял на том, как продолжить:

let rec toRel xs =
    match xs with
    | (a,b)::rest -> (a,[b])::toRel rest
    | _           -> []

1 ответ

Решение

Вы можете использовать встроенную функцию List.groupBy и затем сопоставьте, чтобы удалить избыточный ключ:

testList |> List.groupBy fst |> List.map (fun (k,v) -> (k, List.map snd v))

// val it : (int * string list) list = [(1, ["c"; "b"]); (2, ["a"])]

В противном случае, если вы хотите продолжить матч, вы можете сделать что-то вроде этого:

let toRel x = 
    let rec loop acc xs =
        match xs with
        | (k, b) :: rest ->
            let acc =
                match Map.tryFind k acc with
                | Some v -> Map.add k (b::v) acc
                | None   -> Map.add k [b] acc
            loop acc rest
        | _             -> acc
    loop Map.empty x |> Map.toList

Или используя Option.toList Вы можете написать это:

let toRel x = 
    let rec loop acc xs =
        match xs with
        | (k, b) :: rest ->
            let acc =
                let lst = Map.tryFind k acc |> Option.toList |> List.concat
                Map.add k (b::lst) acc
            loop acc rest
        | _              -> acc
    loop Map.empty x |> Map.toList
Другие вопросы по тегам