配列の要素がStringや、NumberであればindexOfを使った実装が紹介されているのですが、オブジェクト配列に対しては素直にindexOfが使えず、なかなかサンプルが無かったので晒します。
そもそもJavaSciriptのオブジェクト同士の同値判定が無いので、そこを作りこまねばならぬという感じです。
function定義
/**
* 配列に対してSQLのdistinct句的なことをするやつ
* @param fields distinctする対象のフィールドの名前を配列で
* @return filterメソッドに渡すためのfunctionを返す
*/
function distinct(fieldNames) {
var self = this;
return function(item, i, arr) {
return i == indexOf(arr, item, equalsAllFields)
}
// arrのなかにobjが含まれていればそのインデックス番号を返す
// 探し方はcomparatorを使って探す
function indexOf(arr, obj, comparator) {
for(var index in arr) {
if(comparator(obj, arr[index]) == true) return index;
}
return -1;
}
// オブジェクトaとbが fieldNamesに当てられたプロパティーを比較して同じであればtrueを返す
function equalsAllFields(a, b) {
for(var i in fieldNames) {
var f = fieldNames[i];
if(a[f] !== b[f]) return false;
}
return true;
}
}
使い方(nodeコンソールで実行してみた)
> var data = [
{ id: 0000, name: 'hoge', tag: 'tttt' },
{ id: 1111, name: 'hoge', tag: 'tttt' },
{ id: 1111, name: 'hoge', tag: 'gggg' },
{ id: 2222, name: 'fuga', tag: 'gggg' }
];
> data.filter(distinct(["id"]))
[ { id: 0, name: 'hoge', tag: 'tttt' },
{ id: 1111, name: 'hoge', tag: 'tttt' },
{ id: 2222, name: 'fuga', tag: 'gggg' } ]
> data.filter(distinct(["id","tag"]))
[ { id: 0, name: 'hoge', tag: 'tttt' },
{ id: 1111, name: 'hoge', tag: 'tttt' },
{ id: 1111, name: 'hoge', tag: 'gggg' },
{ id: 2222, name: 'fuga', tag: 'gggg' } ]
> data.filter(distinct(["name","tag"]))
[ { id: 0, name: 'hoge', tag: 'tttt' },
{ id: 1111, name: 'hoge', tag: 'gggg' },
{ id: 2222, name: 'fuga', tag: 'gggg' } ]
あ、ネストしたオブジェクトには対応していませんが、一応comparatorを差し替えられるように中途半端に書いてあるのでこの辺をゴネゴネすれば・・・