Scala中有一个字符串列表。让我们假设这些字符串只包含英文字母(小写和大写)。以下是示例清单:
val l1 = List("ab","aa", "bc","Aa", "Ab", "Ba", "BB")
当我们使用以下代码对其进行排序时:
l1.sortWith(_ < _)
我们将收到:
List(Aa, Ab, BB, Ba, aa, ab, bc)
所以这种排序使用了以下字母之间的关系:
A < B < C < ... < a < b < c ...
我们也可以使用:
l1.sortWith(_.toLowerCase < _.toLowerCase)
接收:
List(aa, Aa, ab, Ab, Ba, BB, bc)
所以现在字母之间的关系是:
(a=A) < (b=B) < (c=C) ...
但是如何使用以下字母顺序在Scala中对它们进行排序? :
a < A < b < B < c < C ...
所以结果应该是;
List(aa, ab, Aa, Ab, bc, Ba, BB)
答案 0 :(得分:5)
scala> def compareChar(c1:Char, c2:Char) = {
if ( c1 == c2 ) None
else if (c1.toLower == c2.toLower) Some(c2.isUpper)
else Some(c1.toLower < c2.toLower)
}
compareChar: (c1: Char, c2: Char)Option[Boolean]
scala> def compareString(s1:String, s2:String) : Boolean = {
(s1 zip s2).collectFirst {
case (c1,c2) if (compareChar(c1,c2).isDefined) => compareChar(c1,c2).get
}.getOrElse(s1.length < s2.length)
}
compareString: (s1: String, s2: String)Boolean
scala> l1 sortWith compareString
res02: List[String] = List(aa, ab, Aa, Ab, bc, Ba, BB)
编辑: 内联版本:
def compareString(s1:String, s2:String) : Boolean = {
(s1 zip s2).collectFirst {
case (c1, c2) if c1 == c2 => compareString(s1.tail, s2.tail)
case (c1, c2) if c1.toLower == c2.toLower => c2.isUpper // same letter, different case, uppercase wins
case (c1, c2) => c1.toLower < c2.toLower
}.getOrElse(s1.length < s2.length) // same prefix, the longest string is bigger
}
scala> val l1 = List("ab","aa", "bc","Aa", "Ab", "Ba", "BB")
l1: List[String] = List(ab, aa, bc, Aa, Ab, Ba, BB)
scala> l1 sortWith compareString
res0: List[String] = List(aa, ab, Aa, Ab, bc, Ba, BB)
scala> List("ABC","AB") sortWith compareString
res1: List[String] = List(AB, ABC)
答案 1 :(得分:2)
scala> import math.Ordering.Implicits._
import math.Ordering.Implicits._
scala> val words = List("ab","aa", "bc","Aa", "Ab", "Ba", "BB")
words: List[String] = List(ab, aa, bc, Aa, Ab, Ba, BB)
scala> words sortBy (_ map (c => if (c.isUpper) 2 * c + 1 else 2 * (c - ('a' - 'A'))))
res0: List[String] = List(aa, ab, Aa, Ab, bc, Ba, BB)
答案 2 :(得分:0)
试试这个
val l1 = List("ab","aa", "bc","Aa", "Ab", "Ba", "BB")
def comp[T <: String](a: T, b: T) = {
def _comp(i: Int): Boolean = try {
val (l, r) = (a(i), b(i))
if (l == r) _comp(i+1) else l.toLower < r.toLower
} catch {
case e: IndexOutOfBoundsException => true
}
_comp(0)
}
println(l1.sortWith(comp)) // List(aa, ab, Aa, Ab, bc, Ba, BB)
答案 3 :(得分:0)
tailrec
优化解决方案:
def comp(x: String, y: String): Boolean = {
@tailrec
def go(xs: List[Char], ys: List[Char]): Boolean = {
(xs, ys) match {
case (hx :: tx, hy :: ty) =>
if (hx == hy) go(tx, ty)
else if (hx.toLower == hy.toLower) hx.isLower
else if (hx.isLower) hx < hy
else hx < hy.toUpper
case (Nil, _) => true
case (_, Nil) => false
}
}
go(x.toList, y.toList)
}