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!