Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.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
Scala 对通用对象列表进行排序_Scala - Fatal编程技术网

Scala 对通用对象列表进行排序

Scala 对通用对象列表进行排序,scala,Scala,我需要编写一个对Seq[T]对象执行排序的通用代码。我知道在我们知道基类及其属性之前,将不可能执行排序操作。在研究了这段代码之后,我使用了这段代码,我的要求是处理尽可能多的自定义数据类型 case class Country(name: String, id : Int) type CountrySorter = (Country, Country) => Boolean def byName : CountrySorter = (c1:Country, c2:Country) =>

我需要编写一个对
Seq[T]
对象执行排序的通用代码。我知道在我们知道
基类及其
属性之前,将不可能执行排序操作。在研究了这段代码之后,我使用了这段代码,我的要求是处理尽可能多的自定义数据类型

case class Country(name: String, id : Int)
type CountrySorter = (Country, Country) => Boolean
def byName : CountrySorter = (c1:Country, c2:Country) => c1.name < c2.name
def byId : CountrySorter = (c1:Country, c2:Country) => (c1.id < c2.id)

val sortingMap = Map[String, CountrySorter](
  "sortByCountryName" -> byName ,
  "soryByCountryId" -> byId
 )

input.sortWith(sortingMap(criteria))这里我得到的错误是
sortWith
函数只接受
Country
类型,而不接受
T
类型

使用带有字符串键的
地图对国家进行排序容易出错。更好的替代方法是通过
ordering[A]
type类利用Scala中的排序机制

您可以这样使用它:

def sort[T](input : Seq[T])(implicit order: Ordering[T]): Seq[T] = {
  input.sorted
}
这里的关键是在范围内进行正确的排序。您可以在范围中创建单个临时订购:

def main(args: Array[String]): Unit = {
  implicit val byIdOrdering = Ordering.by((country: Country) => country.id)

  val countries: Seq[Country] = ???
  sort(countries)
}
您可以在case类的伴奏中定义顺序并显式导入它:

object Country {
  implicit val byIdOrdering: Ordering[Country] = 
     Ordering.by((country: Country) => country.id)

  implicit val byNameOrdering: Ordering[Country] = 
     Ordering.by((country: Country) => country.name)
}

import Country.byNameOrdering
def main(args: Array[String]): Unit = {
  val countries: Seq[Country] = ???
  sort(countries)
}
如果您有此类订购规则,也可以使用:

trait LowPriorityCountryImplicits {
  implicit val byNameOrdering: Ordering[Country] = 
    Ordering.by((country: Country) => country.name)
}

object HighPriorityCountryImplicits extends LowPriorityCountryImplicits {
  implicit val byIdOrdering: Ordering[Country] = 
    Ordering.by((country: Country) => country.id)
}

import HighPriorityCountryImplicits._
def main(args: Array[String]): Unit = {
  val countries: Seq[Country] = ???
  sort(countries)
}
如果需要,甚至可以显式地传递订单:

def main(args: Array[String]): Unit = {
  val countries: Seq[Country] = ???
  sort(countries)(Country.byNameOrdering)
}

如果您想使用
sortWith
定义订单,这里有一种方法:

case class Country(name: String, id : Int)

type Sorter[T] = (T, T) => Boolean
type CountrySorter = Sorter[Country]

def byName : CountrySorter = (c1, c2) => c1.name < c2.name
def byId : CountrySorter = (c1, c2) => c1.id < c2.id

def sort[T](input: Seq[T], sorter: Sorter[T]): Seq[T] = {
  input.sortWith(sorter)
}

val countries = List(Country("Australia", 61), Country("USA", 1), Country("France", 33))

sort(countries, byName)
// res1: Seq[Country] = List(Country(Australia,61), Country(France,33), Country(USA,1))

sort(countries, byId)
// res2: Seq[Country] = List(Country(USA,1), Country(France,33), Country(Australia,61))
case类国家(名称:String,id:Int)
类型分拣机[T]=(T,T)=>布尔值
类型CountrySorter=分拣机[国家]
def byName:CountrySorter=(c1,c2)=>c1.namec1.id
使用上述答案后,我用以下代码满足了此要求

作为所有子案例类的父类的通用特征,即仅包含执行排序的字段

 sealed trait Generic{
    def name : String = ???
    def id : Int = ???
    def place : String = ???
  }

 //case class which need to be sorted 
  case class Capital( 
      countryName : String, 
      override val id: Int, 
      override val place:String
 ) extends Generic

  case class Country(
         override val name: String, 
         override val id: Int
  ) extends Generic
分类类型

  type Sorter[T] = (T, T) => Boolean
  type CountrySorter = Sorter[Generic]
  type CapitalSorter = Sorter[Generic]
排序顺序

  def byName : CountrySorter = (c1, c2) => c1.name < c2.name

  def byId : CountrySorter = (c1, c2) => c1.id < c2.id

  def byPlace : CapitalSorter = (s1, s2) => s1.place > s2.place
用名称保存排序顺序的数据结构

  val mapper = Map[String, Sorter[Generic]](
        "name" -> byName, 
        "id" -> byId, 
        "place" -> byPlace
       )
输入

输出

  println(sort(countries,mapper("id")))
 //List(Country(USA,1), Country(France,33), Country(Australia,61))

  println(sort(headQuaters , mapper("place")))
  //List(Capital(France,33,Paris), Capital(America,1,New York), Capital(India,65,New Delhi), Capital(Australia,61,Melbourne))

使用
implicit
不是满足此要求的正确方法,因为我应该动态更改排序顺序,即我需要为每个新排序顺序在范围内引入一个新函数。@puneethredtyv动态性如何?你怎么决定?您总是可以通过自己提供排序来显式地传递排序。在我的需求中,我将从UI获取一个字符串,该字符串描述排序顺序。您在这种方法中使用了显式的,这没有什么错,但是对于这种要求,我怎么可能仅通过
字符串
值在范围内设置排序顺序呢?@puneethredtyv我明白您的意思。我们可以通过在字符串上切换/if-else并在范围内生成正确的顺序来实现这一点,但它可能会比使用
sortWith
更麻烦。谢谢您的回答,并让我的评论令人信服。
  val mapper = Map[String, Sorter[Generic]](
        "name" -> byName, 
        "id" -> byId, 
        "place" -> byPlace
       )
  val countries = List(Country("Australia", 61), Country("USA", 1), Country("France", 33))
  val headQuaters = List(
    Capital("Australia", 61, "Melbourne"), 
    Capital("America", 1, "New York"), 
    Capital("France", 33, "Paris"), 
    Capital("India", 65, "New Delhi")
 )
  println(sort(countries,mapper("id")))
 //List(Country(USA,1), Country(France,33), Country(Australia,61))

  println(sort(headQuaters , mapper("place")))
  //List(Capital(France,33,Paris), Capital(America,1,New York), Capital(India,65,New Delhi), Capital(Australia,61,Melbourne))