Scala:隐式排序问题
Scala: Implicit ordering issue
我正在做书中的练习 Learning Scala,有一个问题问:
A popular use for implicit parameters is for a default setting that
works most of the time but may be overridden in special cases. Assume
you are writing a sorting function that takes lines of text, and the
lines may start with a right-aligned number. If you want to sort using
the numbers, which may be prefixed by spaces, how would you encode
this ability in an implicit parameter? How would you allow users to
override this behavior and ignore the numbers for sorting?
我的解决方案:
def sortLines(l: List[String])(implicit o: Ordering[String]) = l.sorted
使用 Scala 测试的单元测试:
"Ch10" should "order lines starting with right-aligned numbers" in {
val l = List(" 2 a", " 1 b", " 3 c")
implicit val orderingByNumber: Ordering[String] = Ordering.by(_.trim.split("\s")(0).toInt)
val orderingIgnoringNumber: Ordering[String] = Ordering.by(_.trim.split("\s")(1))
Ch10.sortLines(l) should contain inOrder(" 1 b", " 2 a", " 3 c")
Ch10.sortLines(l)(orderingIgnoringNumber) should contain inOrder(" 2 a", " 1 b", " 3 c")
}
问题是测试失败 java.lang.NumberFormatException: For input string: "b"
。为什么?
Ordering.by
具有以下签名:
def by[T, S](f: T => S)(implicit ord: Ordering[S]): Ordering[T]
函数结果类型采用隐式 Ordering
,在您的情况下为 String
。而此时定义的隐式 Ordering[String]
是 orderingByNumber
。所以发生的事情是 orderingIgnoringNumber
从字符串中删除第二个单词,并尝试使用 orderingByNumber
对它们进行排序,后者又尝试将它们转换为 Int
,并抛出异常。
您可以为 orderingIgnoringNumber
尝试此实现:
val orderingIgnoringNumber: Ordering[String] =
Ordering.by((_: String).trim.split("\s")(1))(Ordering.String)
这里明确使用了原来的Ordering[String]
。
我正在做书中的练习 Learning Scala,有一个问题问:
A popular use for implicit parameters is for a default setting that works most of the time but may be overridden in special cases. Assume you are writing a sorting function that takes lines of text, and the lines may start with a right-aligned number. If you want to sort using the numbers, which may be prefixed by spaces, how would you encode this ability in an implicit parameter? How would you allow users to override this behavior and ignore the numbers for sorting?
我的解决方案:
def sortLines(l: List[String])(implicit o: Ordering[String]) = l.sorted
使用 Scala 测试的单元测试:
"Ch10" should "order lines starting with right-aligned numbers" in {
val l = List(" 2 a", " 1 b", " 3 c")
implicit val orderingByNumber: Ordering[String] = Ordering.by(_.trim.split("\s")(0).toInt)
val orderingIgnoringNumber: Ordering[String] = Ordering.by(_.trim.split("\s")(1))
Ch10.sortLines(l) should contain inOrder(" 1 b", " 2 a", " 3 c")
Ch10.sortLines(l)(orderingIgnoringNumber) should contain inOrder(" 2 a", " 1 b", " 3 c")
}
问题是测试失败 java.lang.NumberFormatException: For input string: "b"
。为什么?
Ordering.by
具有以下签名:
def by[T, S](f: T => S)(implicit ord: Ordering[S]): Ordering[T]
函数结果类型采用隐式 Ordering
,在您的情况下为 String
。而此时定义的隐式 Ordering[String]
是 orderingByNumber
。所以发生的事情是 orderingIgnoringNumber
从字符串中删除第二个单词,并尝试使用 orderingByNumber
对它们进行排序,后者又尝试将它们转换为 Int
,并抛出异常。
您可以为 orderingIgnoringNumber
尝试此实现:
val orderingIgnoringNumber: Ordering[String] =
Ordering.by((_: String).trim.split("\s")(1))(Ordering.String)
这里明确使用了原来的Ordering[String]
。