2012-12-02 5 views
1

터플의 두 번째 문자열에 대한 모든 중복을 제거하는 동안 알파벳순으로 튜플의 첫 번째 문자열로 List[(String, String)]을 정렬하는 쉬운 방법이 궁금합니다.스칼라 정렬 속성의 튜플 목록

제안 해 주셔서 감사합니다.

+3

http://stackoverflow.com/a/3912833/298389 + .sortBy (_._ 1) –

답변

7

성능 테스트를 실행할 수 있습니까?

val items = List("a" -> 0, "b" -> 1, "c" -> 0, "d" -> 0, "e" -> 1) 
items.groupBy(_._2).toList 
    .sortBy(_._2.head._1)(new Ordering[String]() { 
     override def compare(x: String, y: String) = { -x.compareTo(y) } 
    }) 
    .map(e => (e._2.head._1 -> e._1)) 

결과 : 호기심에 대한

List((b,1), (a,0)) 
+1

맞춤 주문의 요점은 무엇입니까? 'Ordering [String] .reverse'을 사용하지 않는 이유는 무엇입니까? –

+0

고마워! 결국 기본 주문을 사용하여 끝내 버렸습니다. – Jin

+0

진 (Jin)은 예를 들어 소문자로 문자열을 정렬하고자 할 수 있습니다. 이것이 바로 맞춤 주문이 답변에 사용 된 이유입니다. – idonnie

1

은 코멘트에 링크 된 대답은 여전히 ​​작동합니다.

이미 TreeMap이있는 경우 groupBy는 TreeMaps를 작성합니다. 그 줄은 idonnie와 비슷하지만, 다시 정렬 할 필요는 없습니다.

TreeMap(data: _*) groupBy (_._2) map (p => (p._2.head._1, p._1)) 

상자가없는 목록의 목록에서 TreeMap을 빌드 할 수없는 이유는 확실하지 않습니다. 나는 차가운 약의 안개와 싸우고있다. 그러나 사람들이 이러한 질문을 게시 할 때 항상 재미 있습니다.

package object distinctby { 
    import scala.collection.IterableLike 
    import scala.collection.generic.CanBuildFrom 
    import scala.collection.mutable.{ Set => MutSet } 

    implicit class RichCollection[A, Repr](val xs: IterableLike[A, Repr]) extends AnyVal { 
    def distinctBy[B, That](f: A => B)(implicit cbf: CanBuildFrom[Repr, A, That]) = { 
     val builder = cbf(xs.repr) 
     val i = xs.iterator 
     val set = MutSet[B]() 
     while (i.hasNext) { 
     val o = i.next 
     val b = f(o) 
     if (!set(b)) { 
      set += b 
      builder += o 
     } 
     } 
     builder.result 
    } 
    } 
} 

package distinctby { 
    import scala.collection.generic.CanBuildFrom 
    import scala.collection.immutable.TreeMap 
    object Test extends App { 
    val data = List("eins"->"one","un"->"one","zwei"->"two","deux"->"two") 
    println(data) 
    println(data distinctBy (_._2)) 
    println(TreeMap((data map (_.swap)): _*)) 
    println(TreeMap((data.reverse map (_.swap)): _*)) 
    // groupBy yields a TreeMap of TreeMap, so head is the lexly first 
    println(TreeMap(data: _*) groupBy (_._2) map (p => (p._2.head._1, p._1))) 
    locally { 
     class CBF[A,B](implicit ord: Ordering[A]) 
     extends CanBuildFrom[List[(A, B)], (A,B), TreeMap[A,B]] { 
     def apply(from: List[(A,B)]) = TreeMap.newBuilder[A, B](ord) 
     def apply() = TreeMap.newBuilder[A, B] 
     } 
     implicit def cbf[A,B](implicit ord: Ordering[A]) = new CBF[A,B] 
     println(data.distinctBy[String, TreeMap[String, String]](_._2)(cbf[String, String]).toSeq) 
    } 
    } 
} 

List((eins,one), (un,one), (zwei,two), (deux,two)) 
List((eins,one), (zwei,two)) 
Map(one -> un, two -> deux) 
Map(one -> eins, two -> zwei) 
Map(eins -> one, deux -> two) 
ArrayBuffer((eins,one), (zwei,two)) 
1

난 그냥 튜플의 기본 순서를 수행 할 목록의 sorted 방법을 사용합니다. groupBy (idonnie가 지적한대로)을 사용하여 각 쌍의 두 번째 항목에 대해 고유 한 값을 얻을 수도 있습니다. 여기에 약간의 예제 :

scala> val tuples = scala.util.Random.shuffle("abcd".permutations.map{_.splitAt(2)}.toList) // generate some test data 
tuples: List[(String, String)] = List((cb,ad), (dc,ab), (ba,dc), (bd,ca), (cb,da), (ca,db), (cd,ba), (cd,ab), (db,ca), (ba,cd), (ac,db), (ac,bd), (ab,cd), (ad,cb), (ca,bd), (bd,ac), (ad,bc), (db,ac), (da,bc), (da,cb), (bc,da), (dc,ba), (ab,dc), (bc,ad)) 

scala> tuples.sorted.groupBy(_._2).values.map(_.head).toList.sorted 
res0: List[(String, String)] = List((ab,cd), (ab,dc), (ac,bd), (ac,db), (ad,bc), (ad,cb), (bc,ad), (bc,da), (bd,ac), (bd,ca), (cd,ab), (cd,ba)) 

당신이 유지하기 위해 중복 선택할 수있는 구체적인 방법을 지정하지 않은 나에게 이상한의 종류 것 같다 ...이 첫 번째로 주문한 첫 번째를 (유지한다 string). 나는 당신이 원한다고 가정합니다. 어떤 것을 보관해도 상관 없다면 sorted에 대한 첫 번째 호출을 제거 할 수 있습니다. 첫 번째 호출을 sorted에서 sortBy(_._1)으로 변경하면이 방법이 약간 더 효율적일 수 있지만 실제로 차이가 있는지를 알기 위해 특정 응용 프로그램에 대해 충분히 알지 못합니다.