2015-06-03 12 views
6

Mam krotki postaci (Boolean, Int, String).Scala - sortowanie krotek przez pierwszy element reverse, drugi element regularny

chcę definiować Kolejność który sortuje krotek w następującej kolejności:

  1. Boolean - odwrotnej kolejności
  2. Int - odwrotnej kolejności
  3. String - regularny porządek

Przykład: Dla krotek: Array((false, 8, "zz"), (false,3, "bb"), (true, 5, "cc"),(false, 3,"dd"))

The Zamawianie powinno być:

(true, 5, "cc") 

(false, 8,"zz") 

(false, 3, "bb") 

(false, 3, "dd") 

Czy ktoś może pomóc. Nie mogłem znaleźć sposobu, aby zdefiniować niektóre z zamawianych rewersów i niektóre regularne.

Wielkie dzięki.

Odpowiedz

7

Proste rozwiązanie do przodu w tym konkretnym przypadku jest użycie sortBy na krotki, zmodyfikowany w locie do „odwrócić” pierwszy i drugi element, tak że w końcu kolejność jest odwrotna:

val a = Array((false, 8, "zz"), (false,3, "bb"), (true, 5, "cc"),(false, 3,"dd")) 
a.sortBy{ case (x,y,z) => (!x, -y, z) } 

W przypadkach, gdy nie można łatwo "odwrócić" wartości (powiedzmy, że jest to obiekt referencyjny i masz nieprzejrzysty porządek na nich), możesz zamiast tego użyć sorted i jawnie przekazać zamówienie, które jest konstruowane w celu odwrócenia kolejność na pierwszym i drugim elemencie (można użyć Ordering.reverse do ponownego werset z zamówieniem):

val myOrdering: Ordering[(Boolean, Int, String)] = Ordering.Tuple3(Ordering.Boolean.reverse, Ordering.Int.reverse, Ordering.String) 
a.sorted(myOrdering) 
+0

Świetna odpowiedź. Dzięki!!! – mayap

-1

Możesz zrobić coś takiego.

case class myTuple(t: (Boolean, Int, String)) extends Ordered[myTuple] { 
    def compare(that: myTuple):Int = { 
     val (x,y,z) =t 
     val (x1,y1,z1) = that.t 
     if (x.compare(x1) != 0) x.compare(x1) 
     else { 
      if (y.compare(y1) != 0) if (y.compare(y1) == 1) 0 else 1 
      else z.compareTo(z1) 
     } 
    } 
} 

val myList = Array((false, 8, "zz"), (false,3, "bb"), (true, 5, "cc"),(false, 3,"dd")) 

implicit def tupleToBeordered(t: (Boolean, Int, String)) = new myTuple(t._1,t._2,t._3) 

myList.sorted 
+0

To nie działa, ponieważ nigdzie nie ma nawet 'myTuple'. Twoja konwersja 'tupleToBeordered' nigdy nie jest wywoływana, a' myList' jest nadal zwykłym 'Array [(Boolean, Int, String)], więc' myList.sorted' używa normalnego porządku. Aby to się stało, musisz najpierw przekonwertować 'myList' na kolekcję' myTuple', posortować ją, a następnie przekonwertować z powrotem na kolekcję krotek. Coś jak 'myList.map (tupleToBeordered) .sorted.map (_. T)'. Z drugiej strony, nadal nie działa, ponieważ twój 'porównuj' nie odwraca porównania na' x'. –

Powiązane problemy