6

I'm trying to sort an array of objects. When i try to use sortWith function to sort only one field in the object, it works perfectly fine. When multiple fields are sorted, then it messes up.

For eg.

scala> val res = branches.collect.toList
res: Array[(String, String, String)] = Array((109,A,Australia),     (101,A,Australia), (102,A,Myanmar), (103,B,Australia), (104,A,Europe), (105,B,US), (106,B,Myanmar), (107,C,Australia), (108,A,Canada))

scala> val a = res.sortWith((x,y) => (x._2 < y._2 && x._1 > y._1))

Basically im trying to sort 2nd tuple and based on the result i'm sorting the first tuple. I get the following result, which is not sorted properly. I understand that the same can be achieved with sortBy function also. But i would like to understand how the sortWith works.

scala> val a = res.sortWith((x,y) => (x._2 < y._2 && x._1 > y._1))
a: Array[(String, String, String)] = Array((109,A,Australia), (107,C,Australia), (101,A,Australia), (102,A,Myanmar), (104,A,Europe), (108,A,Canada), (103,B,Australia), (105,B,US), (106,B,Myanmar))
1
  • just to be clear, how do you expect that to be sorted ? can you update your question with the desired output ? Commented Jul 4, 2016 at 7:40

2 Answers 2

12

A simple approach with sortBy,

res.sortBy(t => (t._2, -t._1))

which sorts first by the second item in the tuple in ascending order, and in case of equality, sorts by the first item, in descending order. Note we use of the negation (minus here) to revert the default ordering.

Sign up to request clarification or add additional context in comments.

Comments

10

Your problem is in your predicate. Consider the comparison of (101,A, Australia) with (102,A, Myanmar): Your sort function says the first tuple is smaller when both the second element is smaller and the first element is larger - i.e when A

Similarly, if you reverse the comaprison, is (102,A,Myanmar) < (101,A,Australia)? here you need A

So the sorting algorithm sees these that neither of elements is less than the other, so they are equal for sort purposes, and using a stable sort, leaves them in the original order. Try reversing those two elements in your inoput and see that they appear in the result in the order you put them in.

The sort predicate you need is: (x._2 < y._2 ||(x._2 == y._2 && x._1 > y.1))) - this will first compare the second element of the tuples, so (,A,) will always be less than (,B,_), however when the second elements are equal, it will then indicate less than for case where the first element is larger.

The key here is that you want to use the secondary comparison (x._1>y._1) only when the primary comparison (x._2 with y._2) is equal.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.