如何改进此代码

Ula*_*kar 7 scala

我是斯卡拉新手,刚开始学习这门语言.

我从Project Euler页面解决了问题8.

代码看起来像这样(我删除了读取输入文件所需的所有代码):

def max(n1: Int, n2: Int): Int = Math.max(n1, n2)

def max_product(digits: List[Int], num: Int): Int = {
    def max_core(lst: List[Int], curr_max: Int): Int = lst match {
        case a if lst.length >= num => 
            max_core(a.tail, max(lst.slice(0, num).reduceLeft(_*_), curr_max))
        case _ => curr_max
    }

    max_core(digits, 0)
}

println(max_product(1::2::3::4::2::3::Nil, 2))

它工作正常,结果是正确的.但是,我对这个解决方案并不完全满意.我不喜欢max_core子功能,并且感觉它可以改进.我对FP的理解是,你应该迭代一个列表,切片似乎不是这里的方式.

问题是:如何?

Fla*_*gan 7

首先,我不会重新发明轮子...方法max已定义RichInt,所以你可以写a max b,for ab整数.

此外,slice已被弃用,因此,而不是lst.slice(0, num)我会用lst.take(num).当Scala 2.8启动时,不推荐使用的方法可能会消失.

编辑:事实上,正如丹尼尔指出的那样,slice(Int, Int)并没有被弃用.当我最初写这篇文章的时候我很匆忙,而我正在思考slice(Int),这相当于drop(Int).我仍然觉得lst.take(num)lst.slice(0, num):) 更清楚.

(nitpick)你的最后一行也没有编译,因为你忘了添加Nil到你的序列的结尾.1::2::3::4,最终会调用::一个Int没有这个方法的.这就是为什么你需要添加Nil到结束(调用::Nil).

此外,您使用的算法乍一看并不明显.我写这个的方式如下:

val numbers = /*"--the string of numbers--"*/.map(_.asDigit).toList

def sliding[A](xs: List[A], w: Int): List[List[A]] = {
  for(n <- List.range(0, xs.size - w)) 
    yield xs drop n take w
}

def product(xs: List[Int]): Int = (1 /: xs) (_ * _)

sliding(numbers, 5).map(product).sort(_ > _).head
Run Code Online (Sandbox Code Playgroud)

我觉得最后一行解释得很好什么的算法,应该做的事-以列表的滑动窗口,计算产品在滑动窗口,然后得到最大的计算出产品的(我已经实现了最大的功能sort(_ > _).head出懒惰,我可以做一些O(n)而不是O(n log(n)),如果性能是关键的......它仍然在一秒钟内运行).

请注意,滑动函数将位于Scala 2.8库中(请参阅Daniel的文章,从中我开始编写此滑动定义的灵感来源).

编辑:哎呀...抱歉/:.我只是喜欢它的简洁性以及折叠的初始元素出现在列表之前的事实.您可以等效地写product为以下内容,以便更明确:

def product(xs: List[Int]): Int = xs.foldLeft(1)(_ * _)
Run Code Online (Sandbox Code Playgroud)

-- Flaviu Cipcigan