通过将列表项与其邻居进行比较来对其进行分组

时间:2016-06-14 15:16:45

标签: scala

根据邻居值将值列表分组的最优雅方法是什么?

我所拥有的更广泛的背景是有一个行列表,需要分组成段落。我想能够说,如果两条线之间的垂直差异低于阈值,它们就在同一段中。

我最终以不同的方式解决了这个问题,但我在这里想知道正确的解决方案。

case class Box(y: Int)
val list = List(Box(y=1), Box(y=2), Box(y=5))

def group(list: List[Box], threshold: Int): List[List[Box]] = ???

val grouped = group(list, 2)
> List(List(Box(y=1), Box(y=2)), List(Box(y=5)))

我查看了groupBy(),但一次只能使用一个元素。我还尝试了一种使用sliding()预先计算差异的方法,但是从原始集合中检索元素会变得很尴尬。

1 个答案:

答案 0 :(得分:5)

这是一个班轮。推广类型留给读者练习。

使用整数和绝对差异而不是线条和间距来避免混乱。

val zs = List(1,2,4,8,9,10,15,16)  
def closeEnough(a:Int, b:Int) = (Math.abs(b -a) <= 2)

zs.drop(1).foldLeft(List(List(zs.head)))
                      ((acc, e)=> if (closeEnough(e, acc.head.head)) 
                                      (e::acc.head)::acc.tail
                                  else
                                       List(e)::acc)
       .map(_.reverse)
       .reverse

// List(List(1, 2, 4), List(8, 9, 10), List(15, 16))

或两个衬垫,以获得轻微的效率增益

val ys = zs.reverse
ys.drop(1).foldLeft(List(List(ys.head)))
                ((acc, e)=> if (closeEnough(e, acc.head.head)) 
                   (e::acc.head)::acc.tail
                else
                   List(e)::acc)
// List(List(1, 2, 4), List(8, 9, 10), List(15, 16))