1
votes

I've had good read of the 'Sorting Functions' section of the Julia manual, and had a look at some of the similar questions that have already been asked on this board, but I don't think I've quite found the answer to my question. Apologies if I've missed something.

Essentially I have a vector of vectors, with the enclosed vectors containing integers. For the purposes of the example, each enclosed vector contains 3 integers, but it could be any number. I want to sort the enclosed vectors by the first element, then by the second element, then by the third element etc.

Let's start with the vector:

v = [[3, 6, 1], [2, 2, 6], [1, 5, 9], [2, 1, 8], [3, 7, 9],
    [1, 1, 2], [2, 2, 2], [3, 6, 2], [1, 2, 5], [1, 5, 6],
    [3, 7, 4], [2, 1, 4], [2, 2, 1], [3, 1, 2], [1, 2, 8]]

And continue with what I'm actually looking for:

v = [[1, 1, 2], [1, 2, 5], [1, 2, 8], [1, 5, 6], [1, 5, 9], 
    [2, 1, 4], [2, 1, 8], [2, 2, 1], [2, 2, 2], [2, 2, 6], 
    [3, 1, 2], [3, 6, 1], [3, 6, 2], [3, 7, 4], [3, 7, 9]]

So there should be no requirement for rocket science.

I can easily sort the vector by the first element of the enclosed vectors by one of two ways:

v = sort(v, lt = (x, y) -> isless(x[1], y[2]))

or:

v = sort(v, by = x -> x[1])

Both these methods produce the same answer:

v = [[1, 5, 9], [1, 1, 2], [1, 2, 5], [1, 5, 6], [1, 2, 8],
    [2, 2, 6], [2, 1, 8], [2, 2, 2], [2, 1, 4], [2, 2, 1], 
    [3, 6, 1], [3, 7, 9], [3, 6, 2], [3, 7, 4], [3, 1, 2]]

So, as you can see, I have sorted by the first element of the enclosed vectors, but not by the subsequent elements.

So, to come back to the question in the title, is there a method of sorting by multiple elements using the sort() function?

I can actually get what I want using loops:

for i = 3:-1:1
    v = sort(v, lt = (x, y) -> isless(x[i], y[i]))
end

or:

for i = 3:-1:1
    v = sort(v, by = x -> x[i])
end

However, I don't want to re-invent the wheel, so if there's a way of doing it within the sort() function I'd love to learn about it.

1

1 Answers

5
votes

You can use lexless function as lt keyword argument that does exactly what you want if I understood your question correctly:

julia> sort(v, lt=lexless)
15-element Array{Array{Int64,1},1}:
 [1, 1, 2]
 [1, 2, 5]
 [1, 2, 8]
 [1, 5, 6]
 [1, 5, 9]
 [2, 1, 4]
 [2, 1, 8]
 [2, 2, 1]
 [2, 2, 2]
 [2, 2, 6]
 [3, 1, 2]
 [3, 6, 1]
 [3, 6, 2]
 [3, 7, 4]
 [3, 7, 9]

EDIT: I have just checked that this is a solution for Julia 0.6. In Julia 0.7 you can simply write:

julia> sort(v)
15-element Array{Array{Int64,1},1}:
 [1, 1, 2]
 [1, 2, 5]
 [1, 2, 8]
 [1, 5, 6]
 [1, 5, 9]
 [2, 1, 4]
 [2, 1, 8]
 [2, 2, 1]
 [2, 2, 2]
 [2, 2, 6]
 [3, 1, 2]
 [3, 6, 1]
 [3, 6, 2]
 [3, 7, 4]
 [3, 7, 9]