Sorting 如何在Scala中按词典顺序对列表集合进行排序?
如果Sorting 如何在Scala中按词典顺序对列表集合进行排序?,sorting,scala,html-lists,lexicographic,Sorting,Scala,Html Lists,Lexicographic,如果A具有Ordered[A]特性,我希望能够有这样的代码 val collection: List[List[A]] = ... // construct a list of lists of As val sorted = collection sort { _ < _ } val集合:List[List[A]=…/构建一个As列表的列表 val sorted=集合排序{{u1 案例(Nil,y::ys)=>-1 大小写(x::xs,y::ys)=>(x比较y)匹配{ 案例0=>c(
A
具有Ordered[A]
特性,我希望能够有这样的代码
val collection: List[List[A]] = ... // construct a list of lists of As
val sorted = collection sort { _ < _ }
val集合:List[List[A]=…/构建一个As列表的列表
val sorted=集合排序{{u<}
然后在列表按字典顺序排序的地方得到一些东西。当然,仅仅因为A
具有traitOrdered[A]
并不意味着List[A]
具有traitOrdered[A]
。但是,可以想见,实现这一点的“scala方法”是使用隐式def
假设a具有特征有序[a]
(以便上述代码正常工作),如何将列表[a]
隐式转换为有序[a]
我想在列表[A]
对象上使用词典排序,但我希望代码能够适应其他排序。(11分钟前我实际上不知道如何做,我希望回答我自己的问题是可以的。)
implicit def List2OrderedList[A(11分钟前我还不知道怎么做,我希望可以回答我自己的问题。)
implicit def List2OrderedList[A在2.8中,您应该能够只进行收集。sorted
排序
采用隐式排序
参数。实现排序
的任何类型都有相应的排序
(由于隐式转换排序.排序
)。还有隐式的排序。如果T
具有排序,则Iterable
使Iterable[T]
具有排序
但是,如果您尝试此操作,它将不起作用:
scala> def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted
<console>:5: error: could not find implicit value for parameter ord: Ordering[List[A]]
def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted
^
如果集合的元素类型是List[A],我不确定编译器为什么找不到排序[Iterable[A]]
在2.8中,您应该能够只进行收集。排序的排序的采用隐式的排序
参数。实现排序的任何类型都有相应的排序
(由于隐式转换排序。排序的)。还有隐式的排序。如果T
具有排序,则Iterable
使Iterable[T]
具有排序
但是,如果您尝试此操作,它将不起作用:
scala> def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted
<console>:5: error: could not find implicit value for parameter ord: Ordering[List[A]]
def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted
^
如果集合的元素类型是受Daniel评论启发的List[A]
,我不确定编译器为什么找不到排序[Iterable[A]]
,下面是一个递归版本:
implicit def toOrdered[A <% Ordered[A]](list1: List[A]): Ordered[List[A]] = {
@scala.annotation.tailrec
def c(list1:List[A], list2:List[A]): Int = {
(list1, list2) match {
case (Nil, Nil) => 0
case (x::xs, Nil) => 1
case (Nil, y::ys) => -1
case (x::xs, y::ys) => (x compare y) match {
case 0 => c(xs, ys)
case i => i
}
}
}
new Ordered[List[A]] {
def compare(list2: List[A]): Int = c(list1, list2)
}
}
implicit def toOrdered[A 0
案例(x::xs,Nil)=>1
案例(Nil,y::ys)=>-1
大小写(x::xs,y::ys)=>(x比较y)匹配{
案例0=>c(xs,ys)
案例一=>i
}
}
}
新订购的[列表[A]]{
def比较(列表2:List[A]):Int=c(列表1,列表2)
}
}
关于评论:
我过去认为这更多的是一个品味的问题。有时验证递归函数的正确性更容易,当然,您的版本足够短,没有令人信服的理由选择递归
不过,我对性能的影响很感兴趣。因此我尝试对其进行基准测试:请看。我惊讶地发现递归版本更快(假设我正确地进行了基准测试)。对于长度约为10的列表,结果仍然适用。受Daniel评论的启发,下面是一个递归版本:
implicit def toOrdered[A <% Ordered[A]](list1: List[A]): Ordered[List[A]] = {
@scala.annotation.tailrec
def c(list1:List[A], list2:List[A]): Int = {
(list1, list2) match {
case (Nil, Nil) => 0
case (x::xs, Nil) => 1
case (Nil, y::ys) => -1
case (x::xs, y::ys) => (x compare y) match {
case 0 => c(xs, ys)
case i => i
}
}
}
new Ordered[List[A]] {
def compare(list2: List[A]): Int = c(list1, list2)
}
}
implicit def toOrdered[A 0
案例(x::xs,Nil)=>1
案例(Nil,y::ys)=>-1
大小写(x::xs,y::ys)=>(x比较y)匹配{
案例0=>c(xs,ys)
案例一=>i
}
}
}
新订购的[列表[A]]{
def比较(列表2:List[A]):Int=c(列表1,列表2)
}
}
关于评论:
我过去认为这更多的是一个品味的问题。有时验证递归函数的正确性更容易,当然,您的版本足够短,没有令人信服的理由选择递归
不过,我对性能的影响很感兴趣。因此我尝试对其进行基准测试:看。我惊讶地发现递归版本更快(假设我正确地进行了基准测试).对于长度约为10的列表,结果仍然适用。受Ben Lings答案的启发,我设法找到了按字典顺序排列列表的最简单方法:添加行
import scala.math.Ordering.Implicits._
在进行列表[Int]比较之前,为了确保隐式函数infixOrderingOps
在范围内。受Ben Lings答案的启发,我设法找到了按字典顺序排序列表的最简单方法:添加行
import scala.math.Ordering.Implicits._
在进行列表[Int]比较之前,为了确保隐式函数infixOrderingOps
在范围内。受Ben Lings答案的启发,我编写了自己的排序版本:
def sort[A : Ordering](coll: Seq[Iterable[A]]) = coll.sorted
这相当于:
def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
请注意,排序
被隐式转换为排序[Iterable[A]]
示例:
scala> def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
sort: [A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A])Seq[Iterable[A]]
scala> val coll = List(List(1, 3), List(1, 2), List(0), Nil, List(2))
coll: List[List[Int]] = List(List(1, 3), List(1, 2), List(0), List(), List(2))
scala> sort(coll)
res1: Seq[Iterable[Int]] = List(List(), List(0), List(1, 2), List(1, 3), List(2))
有人询问如何提供您自己的比较功能(例如,\uu>\ u
而不是\u
)。使用排序就足够了。fromsthan
:
scala> sort(coll)(Ordering.fromLessThan(_ > _))
res4: Seq[Iterable[Int]] = List(List(), List(2), List(1, 3), List(1, 2), List(0))
Ordering.by
允许您将值映射到另一种类型,该类型已经有一个排序实例。鉴于元组也已排序,这对于案例类的词典比较非常有用
举个例子,让我们定义一个Int的包装器,应用Ordering.by(u.v)
,其中\uu.v
提取基础值,并显示我们得到了相同的结果:
scala> case class Wrap(v: Int)
defined class Wrap
scala> val coll2 = coll.map(_.map(Wrap(_)))
coll2: List[List[Wrap]] = List(List(Wrap(1), Wrap(3)), List(Wrap(1), Wrap(2)), List(Wrap(0)), List(), List(Wrap(2)))
scala> sort(coll2)(Ordering.by(_.v))
res6: Seq[Iterable[Wrap]] = List(List(), List(Wrap(0)), List(Wrap(1), Wrap(2)), List(Wrap(1), Wrap(3)), List(Wrap(2)))
最后,让我们在成员更多的case类上做同样的事情,重用元组的比较器:
scala> case class MyPair(a: Int, b: Int)
defined class MyPair
scala> val coll3 = coll.map(_.map(MyPair(_, 0)))
coll3: List[List[MyPair]] = List(List(MyPair(1,0), MyPair(3,0)), List(MyPair(1,0), MyPair(2,0)), List(MyPair(0,0)), List(), List(MyPair(2,0)))
scala> sort(coll3)(Ordering.by(x => (x.a, x.b)))
res7: Seq[Iterable[MyPair]] = List(List(), List(MyPair(0,0)), List(MyPair(1,0), MyPair(2,0)), List(MyPair(1,0), MyPair(3,0)), List(MyPair(2,0)))
编辑:
在2.13中,我对上述sort
的定义已被弃用:
warning: method Iterable in object Ordering is deprecated (since 2.13.0):
Iterables are not guaranteed to have a consistent order; if using a type
with a consistent order (e.g. Seq), use its Ordering (found in the
Ordering.Implicits object)
改用:
def sort[A](coll: Seq[Seq[A]])(implicit ordering: Ordering[A]) = {
import Ordering.Implicits._
coll.sorted
}
受Ben Lings回答的启发,我