Scala 是否有与sortWith函数类似的本机分组函数?
有一些库(如Spark和其他Scala扩展)具有可用的“groupWith”函数。此函数允许您将元素与集合的其余部分进行比较,然后使用一个或多个谓词对其进行分组。Scala中似乎没有任何本机功能,但它们确实有sortWith函数,该函数的行为类似,但只是对项目进行排序,而不是对项目进行分组。如果解释不充分,这里有一个小代码示例,可以显示我正在尝试做的事情:Scala 是否有与sortWith函数类似的本机分组函数?,scala,Scala,有一些库(如Spark和其他Scala扩展)具有可用的“groupWith”函数。此函数允许您将元素与集合的其余部分进行比较,然后使用一个或多个谓词对其进行分组。Scala中似乎没有任何本机功能,但它们确实有sortWith函数,该函数的行为类似,但只是对项目进行排序,而不是对项目进行分组。如果解释不充分,这里有一个小代码示例,可以显示我正在尝试做的事情: val list = List(1,2,3,4,5,5) val groupedList = list.groupWith{ (e,c) =
val list = List(1,2,3,4,5,5)
val groupedList = list.groupWith{ (e,c) =>
e == c
}
这是一个非常简单的例子,我想做更复杂的比较,比如
e + 1 == c
所以问题是,是否有任何本机Scala函数可以做到这一点?有什么建议或解决办法吗
更新:
从给出的简单示例来看,似乎不太清楚我想做什么,这里有一个更好的示例:
假设我有一个case类和这些对象的列表:
case class Item(num: Int, color: String)
val list = List(new Item(13, "red"), new Item(14,"red"), new Item(15, "blue"), new Item(16, "red"))
list.groupWith{ (e,c) =>
(e.num -1 == c.num || e.num + 1 == c.num ) && e.color == c.color
}
这应该会返回这样的结果:
res8: List[List[Item]] = List(List(Item(13,red), Item(14,red)), List(Item(15,blue)), List(Item(16,red)))
不确定这是否是您想要的(请查看我对您的问题的评论),但有一种方法定义为
groupBy
,其中List
继承(而不仅仅是List)。您将获得:
scala> val list = List(1,2,3,4,5,5)
list: List[Int] = List(1, 2, 3, 4, 5, 5)
scala> list.groupBy( el => el )
res0: scala.collection.immutable.Map[Int,List[Int]] = Map(5 -> List(5, 5), 1 -> List(1), 2 -> List(2), 3 -> List(3), 4 -> List(4))
scala> list.groupBy( el => el + 1 )
res1: scala.collection.immutable.Map[Int,List[Int]] = Map(5 -> List(4), 6 -> List(5, 5), 2 -> List(1), 3 -> List(2), 4 -> List(3))
基本上,您需要提供从值到键的鉴别器功能,您将得到Map[key,List[value]
这就是您想要的吗?下面是一个实现:
// Takes the list as a parameter, can use pimp-my-library if you want
def groupWith[A](xs: List[A], f: (A, A) => Boolean) = {
// helper function to add "e" to any list with a member that matches the predicate
// otherwise add it to a list of its own
def addtoGroup(gs: List[List[A]], e: A): List[List[A]] = {
val (before, after) = gs.span(_.exists(!f(_, e)))
if (after.isEmpty)
List(e) :: gs
else
before ::: (e :: after.head) :: after.tail
}
// now a simple foldLeft adding each element to the appropriate list
xs.foldLeft(Nil: List[List[A]])(addtoGroup)
}
groupWith(list, { (e: Item, c: Item) =>
(e.num - 1 == c.num || e.num + 1 == c.num) && e.color == c.color})
//| res0: List[List[groups.groups.Item]] =
// List(List(Item(16,red)),
// List(Item(15 ,blue)),
// List(Item(14,red), Item(13,red)))
你能告诉我们,那些不熟悉w/Spark groupWith的人,你在这两种情况下的
groupedList
结果吗?我缺少groupWith
的语义。你只想按顺序分组对,即(1,3,2,3)和(e,e+1),它是返回(1,2)、(2,3)、(2,3)还是仅仅返回(2,3)?因此,如果与组中的任何现有成员相比,事物通过谓词,那么它们最终会进入a组?这显然是O(N^2),可以吗?是的,这比生产代码问题更令人好奇,如果你看看本机的sortWith函数,我会想象它有同样的复杂性。不完全是这样,我知道groupBy函数,但它只允许你与元素本身进行比较,所以基于,比如,数字接近度的分组操作是不可能的这(我认为)。请参阅我的更新以更清楚地了解我在寻找什么。这种方法完全符合函数需要做什么的描述,但我正在寻找Scala固有的东西(即我不需要自己编写的东西).好吧,你不需要自己写。我是为你写的:)据我所知,标准库中没有任何东西能完全满足你的需要。没错,我想这本身就回答了我的问题,这是我将要找到的一个很好的答案,谢谢!