2013-01-12 48 views
0

我是一名scala初學者,正在查看java api的trim()方法,我注意到了副作用,所以我試圖在scala中實現一個功能版本。Java調整方法的scala實現

這裏是java版本:返回

public String trim() { 
int len = count; 
int st = 0; 
int off = offset;  /* avoid getfield opcode */ 
char[] val = value; /* avoid getfield opcode */ 

while ((st < len) && (val[off + st] <= ' ')) { 
    st++; 
} 
while ((st < len) && (val[off + len - 1] <= ' ')) { 
    len--; 
} 
return ((st > 0) || (len < count)) ? substring(st, len) : this; 
} 

我在一個字符串&階版本迭代,當它遇到字符的字符串尾部的空間。整個字符串然後反轉,所以可以訪問尾隨的空白。這個新的字符串被迭代,直到遇到一個空格字符並返回該字符串的尾部。然後再次顛倒此新字符串以保持原始字符串順序:

def trim(stringToTrim : String) : String = { 
    def removePreString[String](list : List[String]) : java.lang.String = list match { 

     case head :: tail => { 
      if(head.toString.equals(" ")){ 
       removePreString(tail) 
      } 
      else { 
       head.toString + tail.mkString 
      } 
     } 
    }//end removePreString 

    val preString = removePreString(stringToTrim.toList) 
    val reveresedString = preString.toList.reverse 
    val reveresedPostString = removePreString(reveresedString) 
    reveresedPostString.reverse 

}//end trim 

此代碼如何改進?扭轉絃樂兩次似乎浪費了?

+0

代碼評論有codereview.stackexchange.com。 –

+0

@Dave牛頓爲什麼代碼審查標籤呢? –

+0

因爲人們使用它而不是在正確的網站上發佈? –

回答

2

您可以使用List的內置dropWhile擺脫任何空間前綴。根據右側的謂詞,沒有對應的放棄。你可以反轉,再次下降,然後再次反轉。這將是相當簡潔:

scala> " foo ".toList.dropWhile(_ == ' ').reverse.dropWhile(_ == ' ').reverse.mkString 
res1: String = foo 

另外,還可以使用將消除雙反經典的FP方法,忽略任何可變本地數據,並沒有明顯的歸納變量:

object Trim 
{ 
    def trim(str: String): String = { 
    def trimTail(sList: List[Char], trimmed: List[Char]): List[Char] = { 
     sList match { 
     case c :: rest if rest.forall(_ == ' ') => (c :: trimmed).reverse 
     case c :: rest => trimTail(rest, c :: trimmed) 
     case Nil => trimmed.reverse 
     } 
    } 

    trimTail(str.toList.dropWhile(_ == ' '), Nil).mkString 
    } 
} 

scala> printf("\"%s\"%n", Trim.trim(" foo is bar ")) 
"foo is bar" 

的內部方法是尾遞歸的,所以你不必擔心用長字符串吹堆棧。

您可能想要考慮在字符串的每個尾部調用forall的事實。幸運的是,只要謂詞不滿足,就會返回「短路」,除非您的字符串具有較大的內部全空間子字符串,否則這可能不會成爲問題。但是如果你有一個非空格的字符串,後面跟着所有的空格,那麼最後一個非空格,它的運行時間大約是字符串長度的n^2

補遺

方法trimTail是內方法。它的範圍在trim(及更高版本)之後關閉,但在此代碼中未被利用。

match所述塊的第一case處理的情況下sList包含第二中的至少一個字符和所有後續字符都是空格(rest.forall(_ == ' '))。 case條款中的if被稱爲警衛。你會注意到,對於守衛來說,布爾表達式不需要被包含在parens中。守門員是這場比賽的守門員。首先,模式部分被驗證,並且如果它獲得了它產生的任何綁定,那麼警衛就可以使用它。然後,對守衛進行評估,並且只有當它通過時,才選擇執行特定的case

第一個和第三個case子句表示當沒有更多字符需要檢查原始字符串或所有剩餘字符都是空格時的終止條件。中間情況將sList中的第一個字符移動到trimmed的前面,並在sList的其餘部分遞歸調用trimTail

積累清單的自然而有效的方法是在前面添加新元素。這自然會導致反向結果,所以當你完成後你需要將它反轉。

+0

很酷,謝謝。你介意一下你的修剪方法是如何工作的嗎?特別是這些行:case c :: rest if rest.forall(_ =='')=>(c :: trimmed).reverse case c :: rest => trimTail(rest,c :: trimmed) case無=> trimmed.reverse –