Я искал элегантный способ написать функцию, которая принимает список элементов и возвращает список кортежей со всеми возможными парами различных элементов, не принимая во внимание порядок, т. Е. (A, b) и ( б, а) следует считать одинаковыми и вернуть только один из них.
Я уверен, что это довольно стандартный алгоритм, и это, вероятно, пример с титульной страницы документации F #, но я не могу его найти, даже не ища в Интернете SML или Caml. Я придумал следующее:
let test = [1;2;3;4;5;6]
let rec pairs l =
seq {
match l with
| h::t ->
yield! t |> Seq.map (fun elem -> (h, elem))
yield! t |> pairs
| _ -> ()
}
test |> pairs |> Seq.toList |> printfn "%A"
Это работает и возвращает ожидаемый результат [(1, 2); (1, 3); (1, 4); (1, 5); (1, 6); (2, 3); (2, 4); (2, 5); (2, 6); (3, 4); (3, 5); (3, 6); (4, 5); (4, 6); (5, 6)] но это выглядит ужасно однотипно.
Мне не нужно проходить через выражение последовательности и затем преобразовывать обратно в список, должно быть эквивалентное решение, включающее только базовые операции со списком или библиотечные вызовы ...
Отредактировано:
У меня также есть этот здесь
let test = [1;2;3;4;5;6]
let rec pairs2 l =
let rec p h t =
match t with
| hx::tx -> (h, hx)::p h tx
| _ -> []
match l with
| h::t -> p h t @ pairs2 t
| _ -> []
test |> pairs2 |> Seq.toList |> printfn "%A"
Также работает, но, как и первый, он кажется излишне сложным и сложным, учитывая довольно легкую проблему. Я думаю, что мой вопрос больше о стиле, и если кто-то может придумать для этого двухслойный.