Sakurai.JJ
Sakurai.JJ

Reputation: 684

Sortperm for matrix sorting in Julia lang

I am using Julia 1.6.1.

B is a matrix. For example,

B =
[ 2 4 4 4 5 ;
  1 2 2 3 5 ;
  1 2 3 3 3 ;
  1 2 2 5 6 ;
  1 3 4 4 4 ; ]

I wanted to sort it forcsing on each row.

sortedB = sortslices( B, dims=1, rev=true)

Then, we get sorted B

sortedB  =
[ 2 4 4 4 5 ; # 1st row of the original matrix B
  1 3 4 4 4 ; # 5th row of the original matrix B
  1 2 3 3 3 ; # 3rd row of the original matrix B
  1 2 2 5 6 ; # 4th row of the original matrix B
  1 2 2 3 5 ;] # 2nd row of the original matrix B

I would like to get the array [1 5 3 4 2]. How can I do that ?

It seems that sortperm does not work.

sortperm( sortslices( B, dims=1, rev=true) )
# ERROR: MethodError; no method matching sortperm(::Matrix{Int64})

Upvotes: 4

Views: 1086

Answers (2)

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

If performance is an issue use a non-allocating version.

julia> sortperm(view.(Ref(B), 1:size(B,1), :), rev=true)
5-element Vector{Int64}:
 1
 5
 3
 4
 2

Here are some benchmarks using BenchmarkTools:

julia> @btime sortperm(view.(Ref($B), 1:size($B,1), :),rev=true);
  376.471 ns (3 allocations: 432 bytes)

julia> @btime sortperm(collect(eachslice($B,dims=1)),rev=true)
  642.683 ns (6 allocations: 496 bytes);

Upvotes: 8

MarcMush
MarcMush

Reputation: 1488

you can use eachrow or eachslice:

julia> C = collect(eachslice(B,dims=1))
5-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:
 [2, 4, 4, 4, 5]
 [1, 2, 2, 3, 5]
 [1, 2, 3, 3, 3]
 [1, 2, 2, 5, 6]
 [1, 3, 4, 4, 4]

julia> sortperm(C,rev=true)
5-element Vector{Int64}:
 1
 5
 3
 4
 2

although this will allocate more than necessary (collect is needed apparently)

Upvotes: 5

Related Questions