How to sort slice of an array in-place in F#

Viewed 131

I want to sort a slice of an array, but the following code doesn't work as expected:

let arr = [|2; 8; 4; 1|]
Array.sortInPlace arr
printfn "%A" arr //1,2,4,8

let mutable arr2 = [|2; 8; 4; 1|]
Array.sortInPlace arr2.[1..]
printfn "%A" arr2.[1..] //8,4,1. Expected: 1,4,8
printfn "%A" arr2 //2,8,4,1. Expected: 2,1,4,8

The mutable keyword has no effect one way or the other.

How do I sort a continuous section of an array in-place in F#?

3 Answers

You can use System.MemoryExtensions to sort Spans. Spans is a view around existing data that won't create any copies.

open System

let ar = [|2; 8; 4; 1|]
ar.AsSpan().Slice(1).Sort() // taking span of array, slicing from 1 index and sort remaining elements
printfn "%A" ar // [|2; 1; 4; 8|]

Note: this is supported only from net5

Solved by using System.Array.Sort. Using C# array instead of F#, but good enough I think.

let arr = [|2; 8; 1; 4|]
System.Array.Sort(arr, 1, arr.Length-1)
printfn "%A" arr //[|2; 1; 4; 8|]

The reason why it doesn't appear to work is because you haven't bound the slice to a name. From the compiler's perspective, the slice in the sortInPlace call is different from the slice where you print some contents.

Bind the slice to a name like so and it will behave as you expect it to:

let arr2 = [|2; 8; 4; 1|]
let slice = arr2.[1..]
Array.sortInPlace slice
printfn "%A" slice
Related