列表合并和减少而不使用内置函数

时间:2018-10-10 15:53:57

标签: scala recursion

考虑示例

library(arm)

by(df, df$category,
   function(x) lapply(subset(x, select = -c(category, outcome)),
                      binnedplot, x$outcome))

合并归约函数采用两个列表和两个函数,其中一个函数充当合并,另一个函数将其归纳为更通用的Integer形式。

通过将两个列表的头部相乘然后使用add来减少合并 使用max合并,然后获取所生成列表的最小值

val a= List(1,2,3)
val b= List(4,5,6)

这可以使用内置函数来实现,但是还有一种更好的方法,而不必以递归方式使用这些函数。

2 个答案:

答案 0 :(得分:1)

这是您的mergeReduce()(据我了解)。

def mergeReduce(a :List[Int], b :List[Int]
               ,f :(Int,Int)=>Int, g :(Int,Int)=>Int) :Int =
  a.zip(b).map(f.tupled).reduce(g)

val a= List(1,2,3)
val b= List(4,5,6)
mergeReduce(a,b,_*_,_+_)           // 32
mergeReduce(a,b,math.max,math.min) // 4

那么,您要替换的“内置”功能是什么?为什么要替换它们?


然后是没有mapreduceziptupled的版本。

def mergeReduce(lsta :List[Int], lstb :List[Int]
               ,f :(Int,Int)=>Int, g :(Int,Int)=>Int) :Int = {

  def merg(x :List[Int], y :List[Int], acc :List[Int] = Nil) :List[Int] =
    if (x.isEmpty || y.isEmpty) acc.reverse
    else merg(x.tail, y.tail, f(x.head,y.head) :: acc)

  def reduc(z: List[Int]) :Int = z match {
    case Nil => -1 //error
    case i :: Nil => i
    case a::b::c => reduc(g(a,b) :: c)
  }

  reduc(merg(lsta, lstb))
}

这使用.isEmpty.reverse.head.tail.unapply(完成模式匹配的方法)。还是“内置”太多了?

答案 1 :(得分:0)

我认为这就是您要寻找的。它仅使用基本的List操作即可一次完成合并和缩减操作:

def mergeReduce[T](a: List[T], b: List[T], merge: (T, T) => T, reduce: (T, T) => T): T = {
  @tailrec
  def loop(a: List[T], b: List[T], res: T): T =
    (a, b) match {
      case (a :: at, b :: bt) => loop(at, bt, reduce(res, merge(a, b)))
      case _ => res
    }

  loop(a.tail, b.tail, merge(a.head, b.head))
}

如果其中一个列表为Nil,这将失败;如果长度不相同,则将静默丢弃较长列表中的值。