Algorithm 合并scala列表中的元素
我正在尝试将以下Java代码段移植到Scala。它获取Algorithm 合并scala列表中的元素,algorithm,scala,Algorithm,Scala,我正在尝试将以下Java代码段移植到Scala。它获取MyColor对象的列表,并合并彼此之间的增量中的所有对象。这似乎是一个可以用Scala的一些功能位优雅地解决的问题。有什么建议吗 List<MyColor> mergedColors = ...; MyColor lastColor = null; for(Color aColor : lotsOfColors) { if(lastColor != null) { if(lastColor.diff(aColor)
MyColor
对象的列表,并合并彼此之间的增量中的所有对象。这似乎是一个可以用Scala的一些功能位优雅地解决的问题。有什么建议吗
List<MyColor> mergedColors = ...;
MyColor lastColor = null;
for(Color aColor : lotsOfColors) {
if(lastColor != null) {
if(lastColor.diff(aColor) < delta) {
lastColor.merge(aColor);
continue;
}
}
lastColor = aColor;
mergedColors.add(aColor);
}
列出合并的颜色=。。。;
MyColor lastColor=null;
用于(颜色A颜色:lotsOfColors){
if(lastColor!=null){
if(lastColor.diff(aColor)
我假设您在列表中以某种方式安排了颜色,使得颜色空间中的颜色“关闭”(即具有较低的diff
值)在列表中相邻。然后我会使用折叠:
val unmergedColors: List[MyColor] = ...
val mergedColors = (Nil:List[MyColor] /: unmergedColors)( (list,c) => {
list match {
case oldc :: rest if (oldc.diff(c) < delta) => oldc.merge(c) :: rest
case _ => c :: list
}
}).reverse
val未合并颜色:列表[MyColor]=。。。
val mergedColors=(Nil:List[MyColor]/:unmergedColors)((List,c)=>{
列表匹配{
case oldc::rest if(oldc.diff(c)oldc.merge(c)::rest
case=>c::list
}
}).反向
这里,我假设merge
被修改为返回前两个合并的新颜色(因此颜色是不可变的);否则,您将oldc.merge(c);在第一种情况下列出
让我们看看这里发生了什么
我们从新颜色的空列表开始。然后,对于未合并列表中的每种颜色,我们有两种情况:
- 合并列表有一个头部,头部的颜色在我们测试的颜色的增量范围内。在这种情况下,合并头部和新颜色,并将保存的列表与新头部一起传递
- 否则,将新颜色添加到增长列表的前面并将其传递
最后,由于我们将这些操作用作堆栈操作,因此我们以颠倒列表来结束。在我看来,这个问题可能会导致围绕到底是什么问题的各种问题。例如:
- 解决方案在列表的初始顺序中是否应该保持不变
- 在进行过程中,是否应针对合并或未合并的值进行差异化
类型C=MyColor
类型Cs=列表[C]
def合并(val增量:双精度,差异:(C,C)=>双精度,颜色:Cs):Cs={
def_mergeHeadAndGTDiff(head:C,tail:Cs):Cs={
val(toMerge,rest)=尾跨(diff(head,_)Nil
案例x::xs=>\u mergeHeadAndGTDiff(newHead,xs)
})
}
颜色匹配{
案例Nil=>Nil
案例x::xs=>\u mergeHeadAndGTDiff(x,xs)
}
}
解决方案如下所示:
我认为,作为一个
流
,这更有效。注意,我假设列表最初是由diff排序的,因为我使用的是span
。如果将其替换为分区
,则不需要这样做。这里有另一个递归解决方案,它的优点是尾部递归(因此不存在堆栈溢出的机会),但缺点是会进行大量列表操作,因此可能是浪费。在最后调用reverse是将输出颜色恢复到输入顺序,但是如果您不关心顺序,则不需要这样做
def processColors(colors: List[Color], delta: Double): List[Color] = {
def process(in: List[Color], accum: List[Color]): List[Color] = in match {
case x :: y :: ys if x.diff(y) < delta => process( x.merge(y) :: ys, accum )
case x :: xs => process( xs, x :: accum )
case Nil => accum
}
process(colors, Nil).reverse
}
def processColors(颜色:List[Color],delta:Double):List[Color]={
def进程(in:List[Color],accum:List[Color]):List[Color]=匹配中{
如果x.diff(y)进程(x.merge(y)::ys,累计),则情况x::y::ys
案例x::xs=>process(xs,x::accum)
案例无=>累计
}
过程(颜色,无)。反转
}
我会尝试折叠:
def merge(lotsOfColor: List[MyColor], delta: Double): List[MyColor] =
lotsOfColor.tail.foldLeft((List(lotsOfColor.head), lotsOfColor.head)) {
case ((mergedColors, lastColor), aColor) if (lastColor diff aColor) < delta =>
(mergedColors, lastColor merge aColor)
case ((mergedColors, _), aColor) => (aColor :: mergedColors, aColor)
}._1.reverse
def合并(lotsOfColor:List[MyColor],delta:Double):List[MyColor]=
lotsOfColor.tail.foldLeft((列表(lotsOfColor.head)、lotsOfColor.head)){
案例((合并颜色,lastColor),A颜色)如果(lastColor差异A颜色)
(合并颜色,lastColor合并颜色)
大小写((合并颜色,u),aColor)=>(aColor::合并颜色,aColor)
}1.相反
或者,稍有不同,
def merge(lotsOfColor: List[MyColor], delta: Double): List[MyColor] =
lotsOfColor.tail.foldLeft((List(lotsOfColor.head), lotsOfColor.head)) {
case ((mergedColors, lastColor), aColor) =>
if ((lastColor diff aColor) < delta)
(mergedColors, lastColor merge aColor)
else
(aColor :: mergedColors, aColor)
}._1.reverse
def合并(lotsOfColor:List[MyColor],delta:Double):List[MyColor]=
lotsOfColor.tail.foldLeft((列表(lotsOfColor.head)、lotsOfColor.head)){
大小写((合并颜色,lastColor),A颜色)=>
if((lastColor diff aColor)
在Scala中使用ListBuffer还有另一个很酷的技巧,以避免最后出现相反的情况:
import scala.collection.mutable.ListBuffer
def merge(lotsOfColor: List[MyColor], delta: Double): List[MyColor] =
lotsOfColor.tail.foldLeft((ListBuffer(lotsOfColor.head), lotsOfColor.head)) {
case ((mergedColors, lastColor), aColor) if (lastColor diff aColor) < delta =>
(mergedColors, lastColor merge aColor)
case ((mergedColors, _), aColor) =>
mergedColors += aColor
(mergedColors, aColor)
}._1.toList
导入scala.collection.mutable.ListBuffer
def merge(lotsOfColor:List[MyColor],delta:Double):List[MyColor]=
lotsOfColor.tail.foldLeft((ListBuffer(lotsOfColor.head)、lotsOfColor.head)){
案例((合并颜色,lastColor),A颜色)如果(lastColor差异A颜色)
(合并颜色,lastColor合并颜色)
大小写((合并颜色),A颜色)=>
合并颜色+=A颜色
(合并颜色,aColor)
}托利斯特
您标记了这个“scale”而不是“scala”--我想您是指后者并修复了它。我认为ams下面的回答是在scala中使用尾部递归的一个极好的例子。您的代码中有一些问题困扰着我。您将颜色合并到lastColor
,但从未使用合并的lastColor
。当差值大于增量时,算法要做的第一件事是将新颜色指定给lastColor
,然后
import scala.collection.mutable.ListBuffer
def merge(lotsOfColor: List[MyColor], delta: Double): List[MyColor] =
lotsOfColor.tail.foldLeft((ListBuffer(lotsOfColor.head), lotsOfColor.head)) {
case ((mergedColors, lastColor), aColor) if (lastColor diff aColor) < delta =>
(mergedColors, lastColor merge aColor)
case ((mergedColors, _), aColor) =>
mergedColors += aColor
(mergedColors, aColor)
}._1.toList