3

I'm looking for a clean way of dynamically sorting a list with the following requirements.

case class Person(name: String, middleName:Option[String], age:Integer) 

Now sorting that is pretty straight forward however if this sort is driven off a UI where a user would do column sorting and the parameters passed back to the server would simply be the column name. Any suggestions to dynamically create this sorting capability?

Thanks in advance

**Updated:

val sortByName = (p :Person) => p.name
val sortByMiddleName = (p: Person) => p.middleName

val mySortMap = Map("name" -> sortByName, "middleName" -> sortByMiddleName)

val sorted = persons.sortBy(mySortMap("name"))

** Update #2

import scala.math.Ordering.Implicits._

type PersonSorter = (Person, Person) => Boolean
val sortByName: PersonSorter = (x:Person, y:Person) => x.name < y.name
// Implicits import takes care of the Option here...
val sortByMiddleName: PersonSorter = (x:Person, y:Person) => x.middleName < y.middleName

val sortingMap: PersonSorter = Map[String, PersonSorter]("name" -> sortByName, "middleName" -> sortByMiddleName)

(Excluded age, but it's the exact same thing)

Now when I have my list, I can easily just do this.

persons.sortWith(sortingMap("name"))

Where "name" is a parameter string passed in from the UI.

C.N
  • 218
  • 1
  • 9

2 Answers2

2

Something like this should do it:

scala> val alice = Person("Alice", None, 20)
alice: Person = Person(Alice,None,20)

scala> val bob = Person("Bob", None, 21)
bob: Person = Person(Bob,None,21)

scala> val charlie = Person("Charlie", None, 18)
charlie: Person = Person(Charlie,None,18)

scala> val persons = List(alice, bob, charlie)
persons: List[Person] = List(Person(Alice,None,20), Person(Bob,None,21), Person(Charlie,None,18))

scala> persons.sortBy(p => (p.age, p.name))
res5: List[Person] = List(Person(Charlie,None,18), Person(Alice,None,20), Person(Bob,None,21))

scala> persons.sortBy(p => (p.name, p.age))
res6: List[Person] = List(Person(Alice,None,20), Person(Bob,None,21), Person(Charlie,None,18))

To dynamically sort by parameters you can define you own sort functions based on the parameters passed as input. So you could write a function that returns a function that is passed into persons.sortBy. That function passed in is the sorting function which could by sortByAge for example. It's the same idea if you need to sort by two or more parameters.

scala> val sortByAge = (p :Person) => p.age
sortByAge: Person => Integer = <function1>

scala> persons.sortBy(sortByAge)
res9: List[Person] = List(Person(Charlie,None,18), Person(Alice,None,20), Person(Bob,None,21))
Brian
  • 20,195
  • 6
  • 34
  • 55
  • That's not exactly what I meant, I managed this part okay. This is under the assumption you know what you want to sort by. If a query parameter comes through a request as sortBy=age then I'd need the sorting to happen on age, next request could be sortBy=name. – C.N Apr 15 '14 at 22:56
  • @Colin See the updated answer. `sortBy` takes a function to do the sorting so you can define and pass your own function to it based on the parameters given as input. – Brian Apr 15 '14 at 23:15
  • @Brain, thanks for the updated answer. I was hoping I could do something like I am doing in the updated question. I'll have to do it slightly different then. Thanks, I'll accept the answer. – C.N Apr 16 '14 at 02:37
0

case class Person(name: String, id: Int)
  def sort[T](list: List[T])(compare: (T, T) => Boolean): List[T] = {
    list.sortWith(compare)
  }
  
  
  val list = List(Person("P2", 1), Country("P1", 10))
    val rl = sort(list)((a, b) => a.name < b.name)

This is plain and simple

agamjain14
  • 82
  • 12