Ger*_*mán 7 functional-programming scala
我有一个带有复选框的项目列表的Scala应用程序,以便用户选择一些,然后单击一个按钮将它们向上移动一个位置(左).我决定编写一个函数来移动某些符合给定谓词的任意类型的元素.所以,如果你有这些元素:
a b c D E f g h I
Run Code Online (Sandbox Code Playgroud)
并且谓词是"大写字符",该函数将返回:
a b D E c f g I h
Run Code Online (Sandbox Code Playgroud)
简而言之,符合谓词的任何连续元素序列都与其左侧的单个元素交换.
我想出了以下丑陋的命令式实现.我希望看到一个很好的,希望可读的功能解决方案.
def shiftUp[T](a:Array[T], shiftable: T => Boolean) = {
val s = new Array[T](a.length)
var i = 0
var j = 0
while(i < a.length)
{
if(!shiftable(a(i)) && i < a.length - 1 && shiftable(a(i+1)))
{
var ii = i + 1
while(ii < a.length && shiftable(a(ii)))
{
s(j) = a(ii)
ii = ii+1
j = j+1
}
s(j) = a(i)
i = ii
}
else
{
s(j) = a(i)
i = i+1
}
j = j+1
}
s
}
Run Code Online (Sandbox Code Playgroud)
编辑:谢谢大家,我希望你喜欢这个练习!
Geo*_*edy 12
这是一个纯粹的功能实现
def shiftElements[A](l: List[A], pred: A => Boolean): List[A] = {
def aux(lx: List[A], accum: List[A]): List[A] = {
lx match {
case Nil => accum
case a::b::xs if pred(b) && !pred(a) => aux(a::xs, b::accum)
case x::xs => aux(xs, x::accum)
}
}
aux(l, Nil).reverse
}
Run Code Online (Sandbox Code Playgroud)
而这里使用内部的可变性更快
import scala.collection.mutable.ListBuffer
def shiftElements2[A](l: List[A], pred: A => Boolean): List[A] = {
val buf = new ListBuffer[A]
def aux(lx: List[A]) {
lx match {
case Nil => ()
case a::b::xs if pred(b) && !pred(a) => {
buf.append(b)
aux(a::xs)
}
case x::xs => {
buf.append(x)
aux(xs)
}
}
}
aux(l)
buf.toList
}
Run Code Online (Sandbox Code Playgroud)
您可以通过foldLeft(也称为/:)这样做:
(str(0).toString /: str.substring(1)) { (buf, ch) =>
if (ch.isUpper) buf.dropRight(1) + ch + buf.last else buf + ch
}
Run Code Online (Sandbox Code Playgroud)
它需要工作来处理空String但是:
def foo(Str: String)(p: Char => Boolean) : String = (str(0).toString /: str.substring(1)) {
(buf, ch) => if (p(ch) ) buf.dropRight(1) + ch + buf.last else buf + ch
}
val pred = (ch: Char) => ch.isUpper
foo("abcDEfghI")(pred) //prints abDEcfgIh
Run Code Online (Sandbox Code Playgroud)
我将把它留作如何将其修改为基于阵列的解决方案的练习
| 归档时间: |
|
| 查看次数: |
2350 次 |
| 最近记录: |