5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptで2つのJSONな配列の差分を抽出する

Posted at

JSONの形で与えられた2つの配列を比較して、差分を抽出したい場合があります。

arr1 = [
  {LawName: "民法", LawNo: "明治二十九年法律第八十九号"},
  {LawName: "商法", LawNo: "明治三十二年法律第四十八号"},
  {LawName: "刑法", LawNo: "明治四十年法律第四十五号"},
  {LawName: "砂防法", LawNo: "明治三十年法律第二十九号"},
  ...
];
arr2 = [
  {LawName: "民法", LawNo: "明治二十九年法律第八十九号"},
  {LawName: "商法", LawNo: "明治三十二年法律第四十八号"},
  {LawName: "砂防法", LawNo: "明治三十年法律第二十九号"},
  ...
];

配列の差分が欲しければ、Array.prototype.filter()Array.prototype.includes()を組み合わせて抽出することが考えられる…のですが、うまくいきません。
→ 参考:js 二つの配列の差分を求める

失敗例
arr1.filter(item => arr2.includes(item)); // return []

arr1[0]arr2[0]は一見同じに見えますが、参照しているものが違うので、Array.prototype.includes()では「同じものは含まれていない」という扱いになってしまうわけですね。
(ちゃんと調べたわけではないですが、Javaのようにequals()をオーバーライドするやり方もできなさそうです。Array.prototype.sort()のように比較関数を指定できれば良いのですが…。)

filter()の中でオブジェクトが同値であるかを判定するコードをゴリゴリ書く、というのも一つの手段です。しかし、arr1の全ての要素についてarr2の全ての要素と比較するとなると、計算量が2つの配列の積になりそうな気がして嫌な感じです。

#文字列にして検索する
連想配列同士の比較には、文字列にして比較する、という手があります。(型を持つオブジェクトだと良くない気はしますが、今回は元がJSONだからへーきへーき。)
そこで、比較対象arr2の配列を文字列にした上で、arr1の各要素について、その要素の文字列表現がarr2の文字列表現に含まれているかどうかによってfilter()してみましょう。

成功例
var str_arr2 = JSON.stringify(arr2); //配列arr2の文字列表現
arr1.filter(item => str_arr2.indexOf(JSON.stringify(item))<0 ); //itemの文字列表現を検索。
// -> [{LawName: "刑法", LawNo: "明治四十年法律第四十五号"},...]

→ 実装例:法技研六法:法令更新内容
ということで、法令リストの更新に対し、更新内容を表示できるようになりました。
Enjoy!

5
2
0

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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?