我的功能是List
Person
case class Person(first:String,last:String,age:Int)
@annotation.tailrec
def groupPersons(persons: List[Person], results: List[List[Person]] = Nil): List[List[Person]] = persons match {
case Nil => results.reverse
case persons => groupPersons(persons.dropWhile(_.first == persons.head.first), persons.takeWhile(_.first == persons.head.first) :: results)
}
的{{1}},如果它们的名字相同,并且它们在列表中彼此相邻。
dropWhile
我想创建此函数的通用版本,该函数也适用于其他类型,并接受传递给takeWhile
和 def group(p: List[P], results: List[List[P]] = Nil, f: (P,P) => Boolean): List[List[P]] = {
p match {
case Nil => results.reverse
case p => group(p.dropWhile(f), p.takeWhile(f) :: results, f)
}
}
的函数。
类似的东西:
{{1}}
无法使上述工作?任何想法如何解决这一问题?
答案 0 :(得分:2)
你大部分都在那里。向group
添加类型参数可以解决一个问题。您的另一个问题是dropWhile
和takeWhile
是谓词(P=> Boolean
),但您想使用带有两个参数的f
。我们可以通过调整f
并部分应用来解决这个问题。最后,span
的效率会比takeWhile
/ dropWhile
def group[P](p: List[P],
results: List[List[P]] = Nil,
f: (P,P) => Boolean): List[List[P]] = {
p match {
case Nil => results.reverse
case p => {
val g = f.curried(p.head)
val (matching, rest) = p.span(g)
group(rest, matching :: results, f)
}
}
}
val xs = List(Person("John", "Doe", 42), Person("Jane", "Smith", 50),
Person("Jane", "Piper", 52), Person("Mary", "Morse", 52))
def matchFirstName(a:Person,b:Person) = a.first == b.first
group(xs, Nil, matchFirstName)
//> res0: List[List[exprs.exprs.Person]] = List(List(Person(John,Doe,42)), List(
//| Person(Jane,Smith,50), Person(Jane,Piper,52)), List(Person(Mary,Morse,52)))
答案 1 :(得分:1)
我不确定这是否需要你,但还有更好的方法:
case class Person(first:String,last:String,age:Int)
val xs = List(Person("John", "Doe", 42), Person("Jane", "Smith", 50), Person("Jane", "Piper", 52), Person("Mary", "Morse", 52))
有一个函数groupBy
:
scala> xs.groupBy(_.first)
res0: Map[String,List[Person]] =
Map(Jane -> List(Person(Jane,Smith,50), Person(Jane,Piper,52)),
Mary -> List(Person(Mary,Morse,52)),
John -> List(Person(John,Doe,42)))
您可以转换为列表:xs.groupBy(_.first).toList
,然后继续处理您的数据。
感谢@Paul,我没有注意到“彼此相邻”的要求。它在我看来就像一个简单的排序应用程序,即sortWith
函数,它接受函数lt:(A, A) => Boolean
,就像你的f
参数一样。