# The sort！function

In matlab, with the code

``````[table, ind]= sort(table)
``````

we get not only the sorted ‘table’, but also the ‘ind’ that contains the information of the positions of the sorted elements in the original table.

What is the counterpart in julia?

With ‘sort!’, we only get the table, but not ind.

I think `sortperm` is what you’re looking for.

``````help?> sortperm
search: sortperm sortperm! partialsortperm partialsortperm! isconcretetype

sortperm(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer])

Return a permutation vector or array I that puts A[I] in sorted order along the given
dimension. If A has more than one dimension, then the dims keyword argument must be
specified. The order is specified using the same keywords as sort!. The permutation is
guaranteed to be stable even if the sorting algorithm is unstable: the indices of equal
elements will appear in ascending order.
``````
6 Likes

thanks a lot! But it is not as convenient as matlab. In matlab, we need only one line

``````[table, ind]= sort(table)
``````

Here in julia, we need two lines

``````ind=sortperm(table)
table = table(ind)
``````
1 Like

Semicolons can help to write two expressions in 1 line:

``````ind = sortperm(table); table = table[ind]
``````

I don’t know if it’s closer to the MATLAB variable model to do `table .= table[ind]` to sort `table` in-place, but in Julia you may need `table` to remain the same instance that might already be shared with other variables. It performs about the same, and there is a `permute!(table, ind)` that does the same thing; you can’t optimize to elementwise `table .= getindex.((table,), ind)` because it overwrites elements that weren’t reordered yet.

1 Like

The number of lines is one thing, but does this imply some superfluous work on the part of Julia? Could it be more efficient to sort the array and produce the indices simultaneously?

1 Like

That was assuming the sort must use `ind`. The more performant equivalent way would be `ind = sortperm(table); sort!(table)`. I don’t know if it’ll be any faster if those were sorted together, or generally multiple arrays being reordered with respect to sorting one of them.

``````sort(tuple.(table, eachindex(table)), by=first)
``````
``````collect(zip(sort(tuple.(table, eachindex(table)), by=first)...))

``````
``````table, ind = (fs(t)=(table[t],t))(sortperm(table))

table, ind = (t=sortperm(table); (table[t],t))
``````

If this desired syntax isn’t directly replicable but is particularly important to you, you can absolutely define your own convenience functions, e.g.:

``````function matlabsort(tbl)
ind = sortperm(tbl)
return (tbl[ind], ind)
end
``````

Julia is not intended to be a 1:1 direct replacement for any other language, including Matlab. There are always going to be functions or features which don’t directly translate, and this isn’t inherently a bug, just a difference in implementation.

This seems to be one of those Matlab-isms where the returns captured from a function depend on the left-hand side of the assignment operation, i.e. `tbl = sort(tbl)` captures only the sorted table but `[tbl,ind] = sort(tbl)` captures both the table and the permuted indices. This style isn’t consistent with how code is written in Julia, where instead you’d always have to write something like `(tbl, _) = sort(tbl)` to disregard the unneeded returns.

In any event, as a breaking change there’s a 0% chance that modifying `Base.sort` like this would be accepted prior to some theoretical future v2.0 of Julia. If someone felt strongly about enabling this, there’s a few potentials ways forward: submit the code as a PR to Julia ( Pull requests · JuliaLang/julia · GitHub ), write up your own package that includes this implementation and share it to the General registry ( How to develop a Julia package (julialang.org) ), or if you only care to have them defined for your own non-shared code just keep a file of such convenience functions handy and import them as needed.

6 Likes

Looks like the second option I referenced, writing your own Matlab-style package, has already been attempted at least once: GitHub - juliamatlab/MatLang: Matlab’s language functions written in Julia. The repo shows no commits in the past 4 years, but the `Project.toml` shows compatibility with at least Julia v1.0, and it seems to add just fine for me in a fresh Pluto environment.

It has a sortM function defined such that

``````using MatLang

v = randn(5)
# v = [-0.14698, 0.279868, -0.216259, -0.699488, 0.933226]

tbl, ind = sortM(v, I=true)
# tbl = [-0.699488, -0.216259, -0.14698, 0.279868, 0.933226]
# ind = [4, 3, 1, 2, 5]
``````
2 Likes