2015-09-20 209 views
-1

下面举例说明,我一直在玩:自定义排序

import collection.immutable.{TreeSet, TreeMap} 
    val ts = TreeSet(9, 23, 1, 2) 
    ts 
    val tm = TreeMap(3 -> "c", 1 -> "a", 2 -> "b") 
    tm 
    // convert a map to a sorted map 
    val m = Map("98" -> List(4, 12, 14), "001" -> List(22, 11)) 
    val t = TreeMap(m.toSeq: _*) 
    t // sorted by key 
    // sort an unsorted map 
    m.toSeq.sortWith((x, y) => x._2(0) < y._2(0)) 

    // add a unsorted map into a sorted map 
    val m1 = Map("07" -> List(3, 5, 1), "05" -> List(12, 5, 3)) 
    val t1: TreeMap[String, List[Int]] = t ++ m1 
    t1 // "001" is the first key 

我可以使用sortWithMap获得自定义排序,如果我想使用使用不同的排序一个TreeMap什么比默认?

回答

2

您不能使用Map的值来定义Map的默认排序。

TreeMap[A,B]的构造函数接受一个隐含的Ordering[A]参数,所以你可以做这样的事情:

// Will sort according to default Int ordering (ascending by numeric value) 
scala> val tm = TreeMap(3 -> "c", 1 -> "a", 2 -> "b") 
tm: scala.collection.immutable.TreeMap[Int,String] = Map(1 -> a, 2 -> b, 3 -> c) 

// A wild implicit appears! (orders descending by numeric value) 
scala> implicit val tmOrd = Ordering[Int].on((x:Int) => -x) 
tmOrd: scala.math.Ordering[Int] = [email protected] 

// Our implicit is implicitly (yeah) used by constructor 
scala> val invTm = TreeMap(3 -> "c", 1 -> "a", 2 -> "b") 
invTm: scala.collection.immutable.TreeMap[Int,String] = Map(3 -> c, 2 -> b, 1 -> a) 

需要注意的是它的安全限制像这样的implicits的范围。如果可以的话,您应该构造一个(非隐式)对象并手动传递它,或者将隐式声明的范围与其他代码可能受其影响的位置分开。

之所以这样做,是因为TreeMap构建在树的顶部,该树使用键的值来维护允许基于键的有效数据读/写的结构约束,这是Map的主要目的。在Map中对值进行排序根本没有意义。

更新:排序逻辑的复杂性并不意味着什么。根据您的意见:

scala> object ComplexOrdering extends Ordering[Int] { 
    | def compare(a: Int, b: Int) = { 
    |  if(a == 3) -1 else if(a == 2 * b) -1 else if(a == 3 * b) 0 else 1 
    | } 
    | } 
defined object ComplexOrdering 

scala> val tm = TreeMap(3 -> "c", 1 -> "a", 2 -> "b") 
tm: scala.collection.immutable.TreeMap[Int,String] = Map(1 -> a, 2 -> b, 3 -> c) 

scala> val tm = TreeMap(3 -> "c", 1 -> "a", 2 -> "b")(ComplexOrdering) 
tm: scala.collection.immutable.TreeMap[Int,String] = Map(3 -> c, 2 -> b, 1 -> a) 
+0

如果我想排序一个更复杂的函数呢?例如,'(x:Int,y:Int)=> {if(x == 3)-1 else if(x == 2 * y)-1 else if(x == 3 * y)0 else 1 }'。 – qed

+1

只要您比较密钥,无论您的订购有多复杂,都无关紧要。我会更新答案来证明这一点。 – tkroman

1

TreeMap被定义为一个类似于地图的类型,其键的指定排序为。这个排序是由给构造一个隐含的参数给定:

new TreeMap()(implicit ordering: Ordering[A]) // For TreeMap[A,B] 

这样你就可以明确地提供自定义Ordering[A]上在建设置一个替代排序。

但是,该类不提供任何(直接)方法来设置基于的排序。根据我的了解,你打电话给.toSeq.sortWith的关于你所能做到的最好的事情,就是你编码自己的收藏类型。