LoginSignup
18
25

More than 5 years have passed since last update.

JavaScriptのオブジェクト配列に対してdistinct的な事(重複を排除した結果を返す)をする

Last updated at Posted at 2015-09-04

配列の要素が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を差し替えられるように中途半端に書いてあるのでこの辺をゴネゴネすれば・・・

18
25
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
25