# Impossible to sort Sym elements

I’m trying to order elements (Sym) from a Tuple. I’ve tried several codes but nothing works.

I will be grateful if anyone can help.

``````using SymPy
using LinearAlgebra

a1 = [Sym("a_\$i^\$j") for i=1 for j=1:2]
a2 = [Sym("a_\$i^\$j") for i=2 for j=1:2]
A = [a1,a2] # conjunto de todas as ações
S = vec(collect(Base.product(A...))) #Cartesian product

SymPy.sort!(S, by = x -> S)
``````

Is that just a typo? `S` should be `x`:

``````SymPy.sort!(S, by = x -> x)
``````
1 Like

You are right, this is the most correct way.
i tried that too.
But the result is still not the desired one:

8-element Array{Tuple{Sym,Sym,Sym},1}:
(a_1^1, a_2^1, a_3^1)
(a_1^2, a_2^1, a_3^1)
(a_1^1, a_2^2, a_3^1)
(a_1^2, a_2^2, a_3^1)
(a_1^1, a_2^1, a_3^2)
(a_1^2, a_2^1, a_3^2)
(a_1^1, a_2^2, a_3^2)
(a_1^2, a_2^2, a_3^2)

The result I want is:

(a_1^1, a_2^1, a_3^1)
(a_1^1, a_2^1, a_3^2)
(a_1^1, a_2^2, a_3^1)
(a_1^1, a_2^2, a_3^2)
(a_1^2, a_2^1, a_3^1)
(a_1^2, a_2^1, a_3^2)
(a_1^2, a_2^2, a_3^1)
(a_1^2, a_2^2, a_3^2)

There is no order defined on the Julia representation of a Sym object, but you can workaround with e.g.

``````sort(S, by = x -> String(Symbol(x)) )
``````
5 Likes

perfect
thank you

`sort` also accepts a keyword argument `lt` (standing for less-than) which defaults to `isless`. Since `isless` doesn’t seem to be useful for `Sym`s, you can set a comparison manually. If you want it to follow the string order, you can do:

``````sort(S, by = first, lt = (x, y) -> string(x) < string(y))
``````

You can also adjust the `by` argument accordingly, as suggested above:

``````sort(S, by = string ∘ first)
``````
2 Likes

thanks @tomerarnon ,

The code, written in this way, is more understandable. But it does not allow to order columns 2 and 3.

I managed to sort all the columns using the following code:

``````S1 = sort(S, by = a -> String(Symbol(a)))
S2 = sort(S1, by = a -> String(Symbol(a)))
S3 = sort(S2, by = a -> String(Symbol(a)))
``````

8-element Array{Tuple{Sym,Sym,Sym},1}:
(a_1^1, a_2^1, a_3^1)
(a_1^1, a_2^1, a_3^2)
(a_1^1, a_2^2, a_3^1)
(a_1^1, a_2^2, a_3^2)
(a_1^2, a_2^1, a_3^1)
(a_1^2, a_2^1, a_3^2)
(a_1^2, a_2^2, a_3^1)
(a_1^2, a_2^2, a_3^2)

It does like this

``````sort(S, lt = (x, y) -> string(x) < string(y) || string(x)==string(y) && string(x) < string(y) || string(x)==string(y) && string(x) < string(y))
``````

and it also doesn’t require a stable sort algorithm that applying sort multiple times does.

You could simplify and generalize with reduce or a comprehension.

2 Likes

The way you used is fine, but note that you can just use `string(...)`, rather than `String(Symbol(...))` as I did in my second example.

However, just to demonstrate that you can in fact sort by any column:

``````# with `lt`
sort(S, by = x->x, lt = (x, y) -> string(x) < string(y))

# or using composition in `by`
sort(S, by = string ∘ (x -> x))
``````

So anything is possible Also, it is now apparent that what you want is simply:

``````sort(S, by = string)
``````

which will sort the entries in lexicographic order of their strings, which in this case will sort by first character, then second character, then third, and so on. So if your variables are named as you’ve shown, this will work.

2 Likes

thanks @tomerarnon

This greatly improved my code.