Подтвердить что ты не робот

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.

4b9b3361

Ответ 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")

Ответ 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|]