JavaScript >> Javascript 文檔 >  >> Tags >> string

JavaScript 字符串乘法性能探索

由於 JavaScript 使用 + 連接字符串 運算符,如果它還允許您使用例如乘以字符串,那就太好了。 str * 10 (至少可以在 Python 中完成)。由於你不能這樣做,並且沒有提供原生字符串乘法方法,我最近探索了一些方法來實現它......

編寫字符串乘法器函數的簡單方法如下:

function mul0 (str, num) {
	if (!num) return "";
	var newStr = str;
	while (--num) newStr += str;
	return newStr;
}

許多 JavaScript 開發人員都知道,這不是最好的方法,因為字符串連接在 Internet Explorer 中可能非常慢。雖然 IE 往往因此而受到批評(幸運的是,IE 團隊正在他們的瀏覽器的下一個版本中解決這個問題),但 Firefox 在字符串連接方面也不是特別快。由於性能問題,典型的字符串乘法方法是構建一個數組和join 它。這是一個不錯的簡短方法:

function mul1 (str, num) {
	return num ? Array(num + 1).join(str) : "";
}

請注意,虛假的 num 在這種情況下可能不需要處理,因為該函數將處理值 0 沒有它就正確。無論如何,這樣做是為了在各種變體中保持功能相同。

不幸的是,mul1 多次乘以大字符串時,Firefox 2 中的速度仍然很慢。小字符串和重複數字可能不明顯,但隨著數字的增加,完成時間以超線性的速度增加。為了尋找更快的解決方案,我嘗試使用正則表達式來減小正在處理的字符串的大小:

var mul2 = function () {
	function mul (str, num) {
		return Array(num + 1).join(str);
	}
	return function (str, num) {
		return num ? str.replace(/^/, mul("$'", num - 1)) : "";
	};
}();

上面將兩個字符串“$'”相乘 " num - 1 次,然後將其用作與字符串開頭匹配的正則表達式的替換 ($' 返回匹配右側的文本)。那表現如何?它在我的 Windows Vista 系統上的 Firefox 2 中提供,數字為 95 毫秒與 29800 毫秒(mul1 ) 使用 2700x2700 字符串長度/乘數時。但是,根據我的測試,這種速度提升似乎僅限於 Firefox,並且在 Safari 3 beta mul2 比替代版本慢得多。

最後,我嘗試創建一個以指數速率乘以字符串的版本:

function mul3 (str, num) {
	if (!num) return "";
	var	orig = str,
		soFar = [str],
		added = 1,
		left, i;
	while (added < num) {
		left = num - added;
		str = orig;
		for (i = 2; i < left; i *= 2) {
			str += str;
		}
		soFar.push(str);
		added += (i / 2);
	}
	return soFar.join("");
}

儘管這可能比您願意專門用於字符串乘法方法的代碼更多,但它是上述版本中平均跨瀏覽器速度最快的。我還嘗試了一些變體,使用從零到兩個數組和各種數組方法(push , concat 等),但以上似乎是四大瀏覽器中平均速度最快的。

請務必親自嘗試測試,並告訴我您的想法以及您將如何改進代碼。

編輯: Kris Kowal 貢獻了 mul4 (如下所示,並添加到測試頁面)。它使用二進制插值,用 Kris 的話來說“它利用了一個有趣的按位標識:(1 << n) == Math.pow(2, n) "。在我的系統上,它比 mul3 快得多 在 Firefox 中,但比 mul3 慢一點 在 IE、Safari 和 Opera 中。由於它的高速和較輕的重量,這看起來像是要擊敗的。在幾個瀏覽器中嘗試測試頁面,看看你的想法。

function mul4 (str, num) {
	var acc = [];
	for (var i = 0; (1 << i) <= num; i++) {
		if ((1 << i) & num)
			acc.push(str);
		str += str;
	}
	return acc.join("");
}

編輯 2: Dojo 開發團隊的 LiuCougar 發布了一篇後續文章,其中包括幾個額外的變體,David Andersson 給我發了電子郵件另外四個變體,包括這個:

function mul8 (str, num) {
	var	i = Math.ceil(Math.log(num) / Math.LN2),
		res = str;
	do {
		res += res;
	} while (0 < --i);
	return res.slice(0, str.length * num);
}

然而,我應該澄清一下,這主要只是學術討論,因為在測試頁面中多次重複各種字符串是一個非常瘋狂的想法。不過,做實驗還是很有趣的。

編輯 3: 可以在 stevenlevithan.com/demo/mul/all.js 上查看為回复此帖子而發布或通過電子郵件發送的所有變體 .為了保持一致性,我對一些函數進行了一些小的調整,例如空格調整和將輸入參數重命名為 strnum .


Tutorial JavaScript 教程
  1. 在函數內部定義監聽函數

  2. 小行星應用程序:第二階段

  3. 構建應用程序時出現react-native-hms-location 錯誤

  4. 19 個適用於 React、Angular 和 Vue.js 的最佳 JavaScript 管理模板

  5. 舊產品 UI 代碼遷移到 React

  6. 我為節點/瀏覽器製作了一個異步服務容器

  7. [視頻] Addy Osmani 的 JavaScript 現狀

  1. Lesky 簡介:用於快速啟動基於 KoaJS 的應用程序的多語言 CLI

  2. 使用 NodeJS 和 Appwrite 構建自定義雲功能!

  3. React:數據獲取的懸念(第 1 部分)

  4. 如何在我的本地環境中模擬 Javascript 中未知的庫?

  5. 帶有 React Hooks 的粘性表頭

  6. 基本的 GIT 命令。

  7. 減少與 For-Loop

  1. 在 next.js 中導入沒有深度嵌套相對路徑的文件

  2. 不健康的代碼:原始過度使用

  3. NPM 和 YARN 最常用的命令!

  4. 開源通用用戶註冊系統——NodeJS React Redux JWT MongoDB