В общем, есть два способа сделать что-то в F #.Вы можете использовать рекурсию явно или использовать существующие функции.В вашем случае вам нужно сделать две вещи во вложенном виде - вам нужно перебрать внешний список и отсортировать внутренние списки.Сортировка может быть выполнена с использованием List.sortBy
, а итерация (проекция) - с помощью List.map
.
Чтобы исправить исходный подход (с использованием рекурсии) - я немного упростил его (потому что вам не нужнофункция loop
- вы можете сделать саму функцию рекурсивной):
let rec sortPositionList list =
match list with
| [] -> []
| hd::tl ->
// Sort the list of positions first - by storing this as a new value
// using 'let', you get more readable code (and you can use IntelliSense
// to explore the type of 'sorted' and understand what's going on)
let sorted = List.sortBy (fun (x, _) -> x) (GetInternStruct(hd))
// As Brian suggests, more idiomatic F# encoding of the line would be:
// let sorted = GetInternStruct(hd) |> List.sortBy (fun (x, _) -> x)
// but both of the options would work in this case.
// Note: The result shouldn't be wrapped in '[ .. ]'. The operator '::'
// takes an element and a list and returns a new list created by
// prepending the element in front of the list
sorted::(sortPositionList tl)
Решение с использованием существующих функций (List.map
) уже опубликовано JDU.Я бы просто добавил, что он использует частичное применение функции - поэтому параметр, переданный в List.map
, является функцией.Если это вызывает недоумение, вы можете переписать это с использованием лямбда-функции в явном виде:
let SortPositionList (positionList) =
List.map (fun positions ->
List.sortBy (fun (index, _) -> index) positions) positionList
Что может быть написано более идиотски с использованием оператора конвейеризации и функции fst
вместо явного параметра лямбда (как упоминал Брайан):
let SortPositionList (positionList) =
positionList |> List.map (fun positions ->
positions |> List.sortBy fst)
Это означает то же самое, что и код, опубликованный JDU, но вы можете найти его более читабельным.Наконец, вы можете написать то же самое, используя выражения последовательности (что, пожалуй, является наиболее элегантным вариантом):
let SortPositionList (positionList) =
[ for positions in positionList do
yield positions |> List.sortBy fst ]
EDIT Функции, которые я здесь написал, работают со значениямитипа (int*Point) list list
, а не типа Positions list
.Чтобы изменить это, вам нужно добавить некоторые упаковки и распаковки.Рекурсивная реализация должна быть:
match list with // List is always 'Positions', so we use pattern
| Positions [] -> [] // matching to unwrap the underlying list in
| Positions (hd::tl) -> // both cases
// Wrap the resulting list into the positions type
let sorted = Positions(List.sortBy (fun (x, _) -> x) (GetInternStruct(hd)))
(sorted::(sortPositionList tl))
Аналогично, для реализации List.map
:
let SortPositionList (positionList) =
positionList |> List.map (fun (Positions positions) -> // pattern matching
positions |> List.sortBy fst |> Positions) // wrapping