我们如何根据相邻元素之间的差异在scala中拆分列表。例如给定List(1,3,6,10,12,14)和差异3,该函数将返回List(List(1,3),List(6),List(10,12,14))。 / p>
我们可以使用foldLeft来做到这一点吗?我试图创建一个函数
def splitDiff(list:List[Int],diff:Int) =
def func(list:List[List[Int]],m:Int):List[List[Int]] = //compare with last element
list.foldLeft(List(List(0))).foldLeft(func)
但内在功能似乎很难?有什么帮助吗?
答案 0 :(得分:2)
嗯,我有一个解决方案,但我怀疑一个人可以做得更好:
(test.head :: test).sliding(2).toList.map( (pair: List[Int]) => (pair(1), pair(1) - pair(0)) )
.foldLeft(List(List.empty[Int])){ (acc, pair) =>
if (pair._2 < 3) (pair._1 :: acc.head) :: acc.tail else List(pair._1) :: acc }
请注意,这会产生“双重反转”顺序的结果:
res3: List[List[Int]] = List(List(14, 12, 10), List(6), List(3, 1))
可以通过在函数末尾添加.map(_.reverse).reverse
来纠正。
编辑 - 替代尝试:
def func(is: List[Int], diff: Int): List[List[Int]] = {
def loop(is: List[Int], prev: Int, acc: List[List[Int]]): List[List[Int]] = is match {
case Nil => acc
case h :: t if (h - prev < diff) => loop(t, h, (h :: acc.head) :: acc.tail)
case h :: t => loop(t, h, List(h) :: acc)
}
loop(is, is.head, List(List.empty[Int]))
}
再次,给出了双重反转形式的解决方案。
答案 1 :(得分:1)
使用foldLeft的另一个解决方案:
scala> val x = List(1,3,6,10,12,14)
x: List[Int] = List(1, 3, 6, 10, 12, 14)
scala> val y = x.foldLeft((x.head,List[Int](),List[List[Int]]()))
((x,y)=> if((y- x._1) <3) (y,y :: x._2,x._3) else (y,List(y), x._2 :: x._3))
y: (Int, List[Int], List[List[Int]]) = (14,List(14, 12, 10),List(List(6), List(3
, 1)))
scala> val ans = y._2 :: y._3
ans: List[List[Int]] = List(List(14, 12, 10), List(6), List(3, 1))
答案 2 :(得分:0)
请记住,这是未经测试的:
def splitListDiff(li: List[Int], diff: Int): List[Int] =
{
li match {
case hd :: tl => if (hd - tl < diff) hd :: splitListDiff(tl, diff) else return li ++ splitListDiff(tl, diff)
case _ => return li
}
}
但是你想要一个利用foldleft的解决方案吗?
答案 3 :(得分:0)
以下工作无需额外的倒车。由于OP没有说列表的元素是否总是按升序排列,我认为使用Math.abs
也是好的:
def splitDiff(diff: Int)(xs: List[Int]): List[List[Int]] = xs match {
case Nil => Nil
case h :: t =>
val head = h :: ((xs zip t) takeWhile {
case (a,b) => Math.abs(b-a) < diff
} map (_._2))
head :: splitDiff(diff)(xs drop head.length)
}
这种方法的缺点是尾巴被反复拉链。但是,这可以通过封装匹配并在开头只压缩一次来轻松避免。