これが私の最初のアイデアでした。
function isSubsetOf(elements, set) {
var i, l = elements.length, pos;
set = set.split('');
for (i = 0; i < l; i += 1) {
pos = set.indexOf(elements.charAt(i));
if (pos == -1) return false;
set.splice(pos, 1);
}
return true;
}
/*-- Algorithm: --*/
// for each character in *elements*:
// remove that character from an array of *set*'s characters
// (and if not found, return false).
しかし、IE に がないことを知らなかったので、 IE に標準準拠の機能が追加されArray.indexOf
た IE でのパフォーマンスという点では、これはひどい敗者になっています。しかし、驚いたことに、それは明らかに卑劣なスプライスクランチマシンである Chrome で悲鳴を上げるだけです。indexOf
Array.prototype
私の 2 番目のアイデアは、最初のアイデアよりもはるかにうまく機能しますが、ページの他のアイデアよりも大幅に優れているわけではありません。
function isSubsetOf2(elements, set) {
var i, l, counts = {};
for (i = 0, l = set.length; i < l; i += 1) {
char = set.charAt(i);
counts[char] = (counts[char] || 0) + 1;
}
for (i = 0, l = elements.length; i < l; i += 1) {
char = elements.charAt(i);
if (!counts[char]) return false;
counts[char] -= 1;
}
return true;
}
/*-- Algorithm: --*/
// For each character in *set*:
// increment its count in an object "map".
// For each character in *elements*
// decrement its count in an object map
// (and if < 0 or doesn't exist, return false)
最後に、私の 3 番目のアイデアは Firefox で最速であり、万能の優れた候補ですが、ブラウザによって機能ごとにかなり異なる速度プロファイルが表示されます。
function isSubsetOf3(elements, sets) {
var e, s, el = elements.length, sl = sets.length;
elements = elements.split('').sort();
sets = sets.split('').sort();
for (e = 0, s = 0; e < el; e += 1, s += 1) {
while (s < sl && sets[s] < elements[e]) { s += 1; }
if (s == sl || sets[s] > elements[e]) { return false };
}
return true;
}
/*-- Algorithm: --*/
// Sort arrays of the characters in *elements* and *set*.
// Do a logical "merge join" (cool!) and:
// if no match is found, return false
// MERGE JOIN:
// For each character in the *elements* array ("left" input)
// Consume one matching character from *set* ("right" input)
// (skipping matches that are less than the character)
// And if *set* runs out of characters or is higher than *element*, return false
入力がソートされている場合、マージ結合は高速です。どうやら、ブラウザーで 2 つの配列を並べ替える方が、文字列ごとに複数の正規表現操作を行うよりも高速です。
編集: 私のアイデア #2 は基本的に Kolink のアルゴリズムの複製であることに気付きました。ただし、私の関数には一貫したパフォーマンス エッジがあります。それらの違いを分析すると、いくつかの興味深い結果が見つかるかもしれません。
また、#2 では、1 行上に移動するべきではなかっcounts[char] -= 1;
たことがわかりましたが、jsperf で既に得たパフォーマンス結果を吹き飛ばしたくありません。関数のパフォーマンスを損なうだけなので、結果を不当に歪めることはないので、そのままにしておきます。
jsperf で速度テストを自分で行ってください。