Если задан список (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