JavaScript: Array.prototype.uniq
Array.prototype.uniq = function(){
for (var i=0,l=this.length; i<l; i++) {
if (this.indexOf(this[i]) < i) {
this.splice(i--, l-- && 1);
}
}
return this;
};
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9].uniq() // -> [3, 1, 4, 5, 9, 2, 6, 8, 7]
もう同じアプローチの解法は出てるんだけど、lengthを変数に取っておくとちょっと効率化できる。
あと、問答無用で破壊するのがJavaScript流だと思うので、そうした。
潰したくないときは、ary.concat().uniq()のように事前に複製する。
Core JavaScript 1.5 Reference:Global Objects:Array:indexOf - MDC
Array#indexOfは普通に===演算子でチェックする。
ハッシュを使ってのfor...in構文だと要素がオブジェクトのときとか困るし、意外と悪くないアプローチに思える。
問題はArray#indexOfが1.6の新機能なのと、[1,2] === [1,2]がfalseになるあたり……
unevalでmap、uniq、evalでmapとかかなあ。
[1, "2", {a: 3}, [4, 5], 1, "2", {a: 3}, [4, 5], 6].uniq()
// -> [1, "2", Object a=3, [4, 5], Object a=3, [4, 5], 6]
[1, "2", {a: 3}, [4, 5], 1, "2", {a: 3}, [4, 5], 6].map(uneval).uniq().map(eval)
// -> [1, "2", Object a=3, [4, 5], 6]
// 非破壊
追記
Array#indexOfだと最後まで走査してしまって無駄が多いので、ちょっと効率化。
Array.prototype.uniq = function(){
for (var i=0,l=this.length; i<l; i++) {
for (var j=0; j<i; j++) {
if (this[i] === this[j]) {
this.splice(i--, l-- && 1);
}
}
}
return this;
};