F # Seq.sortBy в порядке убывания
Я новичок в F # и пришел к функции Seq.sortBy, но сортирует список в порядке возрастания. Как мне получить сортировку в порядке убывания с помощью Seq.sort?
Например, пример кода будет...
let DisplayList =
seq{0..10}
|> Seq.sortBy(fun x -> x)
|> Seq.iter(fun x -> Console.WriteLine(x.ToString()))
дает мне результат 1 2 3 4 5 6 7 8 9 10, когда я действительно хочу, чтобы он делал это с 10 до 1.
Ответы
Ответ 1
Глядя на другие ответы, будьте осторожны с унарным минусом и MININT:
let a = [| 1; -1; System.Int32.MinValue; 0; System.Int32.MaxValue; 1 |]
printfn "%A" (a |> Array.sortBy (fun x -> x))
// [|-2147483648; -1; 0; 1; 1; 2147483647|]
printfn "%A" (a |> Array.sortBy (fun x -> -x)) // uh-oh!
// [|-2147483648; 2147483647; 1; 1; 0; -1|]
Я думаю, что вам действительно нужен минус-x-минус-один:
printfn "%A" (a |> Array.sortBy (fun x -> -x - 1))
// [|2147483647; 1; 1; 0; -1; -2147483648|]
для целочисленного целочисленного типа, который охватывает -2^N..2^N-1
.
Ответ 2
Еще короче:
seq { 0..10 }
|> Seq.sortBy (~-) // Unary minus
|> Seq.iter (printfn "%d")
Ответ 3
F # 4.0 (Visual Studio 2015) введены Seq.sortByDescending
и Seq.sortDescending
let DisplayList =
seq { 0..10 }
|> Seq.sortDescending ' or |> Seq.sortByDescending id
|> Seq.iter Console.WriteLine
См. https://github.com/Microsoft/visualfsharp/wiki/F%23-4.0-Status и https://github.com/fsharp/FSharpLangDesign/blob/master/FSharp-4.0/ListSeqArrayAdditions.md
Ответ 4
Во-первых, продолжите Seq
с помощью функции sortWith
, такой же, как List и Array.
namespace Microsoft.FSharp.Collections
module Seq =
let sortWith f e =
let e' = e |> Seq.toArray
e' |> Array.sortInPlaceWith f
e' |> Seq.readonly
Затем продолжите Operators
с помощью часто используемой функции flip
.
namespace Microsoft.FSharp.Core
module Operators =
let flip f x y = f y x
Теперь мы можем использовать общую функцию compare
для общего (вы можете использовать ее с любой последовательностью сопоставимых элементов) и безопасную (по отношению к наблюдению Брайана) сортировку обратной последовательности.
{0..10}
|> Seq.sortWith (flip compare)
|> Seq.iter (printfn "%A")
Ответ 5
Другой вариант - обернуть System.Linq.Enumerable.OrderByDescending()
:
// #r "System.Core"
module Seq =
let sortByDesc f s = Enumerable.OrderByDescending(s, new Func<'a, 'b>(f))
{0..10} |> Seq.sortByDesc (fun x -> x)
Ответ 6
Вы можете исправить это, предоставив отрицательную клавишу
let DisplayList =
seq { 0..10 }
|> Seq.sortBy (fun x -> -x)
|> Seq.iter (fun x -> Console.WriteLine(x.ToString()))
Также немного проще (и безопаснее) использовать функции printf
для отображения текста в F #. Например
let DisplayList =
seq { 0..10 }
|> Seq.sortBy (fun x -> -x)
|> Seq.iter (printfn "%d")
Ответ 7
Если вы заранее знаете, что у вас будет относительно небольшая последовательность, я думаю, что это более читаемо...
let x = seq { 0.. 10 } |> Seq.toArray |> Array.rev
Конечно, это не рекомендуется, если у вас есть потенциально очень большая последовательность.
Ответ 8
Решения, использующие унарный минус: (fun x -> -x - 1)
и (fun x -> -x)
, не работают, если у вас есть неподписанные типы:
let a = [| 0uy; 255uy; 254uy; 1uy |]
printfn "%A" (a |> Array.sortBy (fun x -> -x - 1))
// error FS0001: The type 'byte' does not support the operator '~-'
Вместо этого мы можем использовать тот факт, что -x = ~~~x + 1
, где ~~~
- оператор побитового отрицания и, следовательно, -x - 1 = ~~~x
. Итак, короткое решение, которое работает как для подписанных, так и для неподписанных типов:
Array.sortBy (~~~) // equivalent to Array.sortBy (fun x -> ~~~x)
Примеры:
let a = [| 0uy; 255uy; 254uy; 1uy |]
printfn "%A" (a |> Array.sortBy (~~~))
// [|255uy; 254uy; 1uy; 0uy|]
let a = [| 1; -1; System.Int32.MinValue; 0; System.Int32.MaxValue; 1 |]
printfn "%A" (a |> Array.sortBy (~~~))
// [|2147483647; 1; 1; 0; -1; -2147483648|]