2011-11-24 56 views
4

這是我的previous question的後續行爲。我注意到,如果我操縱兩個字符串(例如獲得最長的公共前綴,計算兩個字符串之間的差異等),我傾向於使用zip(如在(s1 zip s2)...中)。使用zip查找Scala中兩個字符串之間的差異

它看起來不錯,但可能效率低下(與命令式代碼相比)。這是對的嗎 ?也許,如果性能確實重要,我應該使用命令式算法。

現在我試圖找出兩個字符串是否有區別。你會推薦使用zip來做到嗎?

回答

2

由於您不需要創建元組,所以使用(s1,s2).zipped(s1 zip s2)稍微更高效;而是創建帶有兩個參數的函數。

更重要的是效率而不是易用性的是定義你自己的專業字符串的文件夾:如果你想找到的最長公共前綴的長度

abstract class StrFold[@specialized T](var result: T) { 
    def apply(c1: Char, c2: Char): Unit 
    def done: Boolean 
} 
def strfold[@specialized T](s1: String, s2: String)(folder: StrFold[T]): T = { 
    var i = 0 
    val L = math.min(s1.length, s2.length) 
    while (i < L) { 
    folder(s1.charAt(i), s2.charAt(i)) 
    if (folder.done) return folder.result 
    i += 1 
    } 
    folder.result 
} 

現在,你

class LcpFind extends StrFold(0) { 
    var done = false 
    def apply(c1: Char, c2: Char) { if (c1 == c2) result += 1 else done = true } 
} 
def lcp(s1: String, s2: String) = strfold(s1,s2)(new LcpFind) 

這是一個相當不錯的工作 - 可以說與寫出命令式或遞歸式功能代碼來計算LCP時沒有摺疊式逃逸子句幾乎一樣。

但是它應該幾乎和每次手寫低級字符串的東西一樣快。 (唯一的損失應該是每次創建(小)LcpFind對象,如果您真的想要通過在對話之間重置result來重置它,或者您可以修改StrFoldstrfold來實現並調用reset方法,請更改該輸入參數被命名爲zero並且具有單獨的result方法。)

2

是的,由於兩個原因,效率會降低。

  1. 您正在創建與較短字符串長度相同的字符對列表。這將比原來的兩個字符串佔據更多的位置。尋找最長共同前綴或檢查字符串是否在一個字符中不同的常用方法不需要任何附加內存。

  2. 找到LCP時,您不一定需要遍歷整個字符串。由於zip確實需要這樣做,因此首先壓縮它們顯然效率較低。

但是,這並不意味着你必須使用命令式算法:正常的尾遞歸函數算法也可以執行。

2

它看起來不錯,但可能效率低下(與命令式代碼相比)。

它複製兩個輸入端,因此它有效地是O(Ñ)空間,同時尋找最長公共前綴可以在O(1)時間存儲器。另外,O(len(LCP))時間足夠了(儘管在最壞的情況下這是O(n)時間),並且它進行內存分配,但需要O(n)這是一個昂貴的操作。

現在我試圖找出兩個字符串是否恰好在一個字符中不同。你會推薦使用zip來做到嗎?

取決於字符串的長度和性能是否至關重要。對於第一次拍攝,可能使用zip即可。

1

執行zip時,您可以使用view進行延遲評估(因此它只會壓縮所做的操作)。

相關問題