Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sorting 如何在Scala中按词典顺序对列表集合进行排序?_Sorting_Scala_Html Lists_Lexicographic - Fatal编程技术网

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
具有trait
Ordered[A]
并不意味着
List[A]
具有trait
Ordered[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回答的启发,我