原文地址:http://www.davidflanagan.com/2009/08/string-multipli.html
原作者:David Flanagan
在Ruby中,“*”操作符用一個字串作為左邊參數,一個數字作為右邊參數,來實現字串重複。例如,"Ruby" * 2 的值為 "RubyRuby"。這僅在少數地方有用(例如,產生一張由連字號等ASCII 碼字元構成的表格),但是非常簡潔。而且好過寫一個迴圈來串連n次字串——這樣顯得很沒效率。
我剛剛發現在JavaScript中有個聰明的技巧來實現字串的乘法:
複製代碼 代碼如下:String.prototype.times = function(n) {
return Array.prototype.join.call({length:n+1}, this);
};
"js".times(5) // => "jsjsjsjsjs"
這個方法是調用一個由元素全為“undefined”的數組的Array.join()行為。但是它並沒有真正建立一個包含 n+1 個“undefined”元素的數組。它利用一個包含 length 屬性的匿名對象,依靠 Array 對象的原型函數 join()。因為 “Object” 不是數組,不能直接調用 join(),因此不得不通過原型的 call() 來實現。下面給出一個同樣效果的簡單版本:
複製代碼 代碼如下:String.prototype.times = function(n) { return (new Array(n+1)).join(this);};
當我們調用 Array 的帶一個參數的構造器時,僅僅是設定了數組的長度,實際上並沒有建立數組的元素。
我僅在 Firefox 下對其做了測試,我估計它會比普通的迴圈更加有效,但我並沒有進行基準測試。
作者簡介
David Flanagan 是一個醉心於Java寫作的電腦程式員,他的大部分時間都致力於編寫Java相關圖書。David 在麻省理工學院獲得了電腦科學於工程學位。他生活在地處西雅圖和溫哥華之間的美國太平洋西北海岸。他在O'Reilly出版的暢銷書有《Java in a Nutshell》、《Java Foundation Classes in a Nutshell》、《Java Enterprise in a Nutshell》、《JavaScript: The Definitive Guide》、《JavaScript Pocket Reference》以及《The Ruby Programming Language》等。
我的評論
如果要考慮效率的話,對迴圈迭代稍作最佳化可能效率更高。比如下面這段遞迴調用,演算法複雜度是O(log2n)。在Google Chrome下測試結果是比 David 的方法執行更快,但不得不承認他的方法很優雅! 複製代碼 代碼如下:String.prototype.times = function(n) {
if ( n == 1 ) {
return this;
}
var midRes = this.times(Math.floor(n/2));
midRes += midRes;
if ( n % 2 ) {
midRes += this;
}
return midRes;
}
後記
David 採納了我的建議,他又為我們寫了一段非遞迴的版本。請參看他的部落格原文:http://www.davidflanagan.com/2009/08/good-algorithms.html
連絡方式
我的郵箱,歡迎來信(redraiment@gmail.com)