ソフトウェア開発では、2 つのオブジェクト間の違いを判断することが必要になることがよくあります。これは、プリミティブ データ型を扱う場合は簡単なプロセスですが、ネストされたプロパティ、配列、その他の複雑な構造を含む深いオブジェクトを扱う場合はより複雑になります。
最近遭遇したこの課題に取り組んだ結果、一般的な深差分アルゴリズムが最も効果的なアプローチであることがわかりました。これには、両方のオブジェクトを再帰的に走査し、それらの値を比較し、違いを表す結果オブジェクトを生成することが含まれます。
これを実現するために、次のソリューションを開発しました。
const deepDiffMapper = { VALUE_CREATED: 'created', VALUE_UPDATED: 'updated', VALUE_DELETED: 'deleted', VALUE_UNCHANGED: 'unchanged', map: function(obj1, obj2) { // Handling functions and primitive values separately. if (this.isFunction(obj1) || this.isFunction(obj2)) { throw 'Invalid argument. Function given, object expected.'; } if (this.isValue(obj1) || this.isValue(obj2)) { return { type: this.compareValues(obj1, obj2), data: obj1 === undefined ? obj2 : obj1 }; } // Building a diff object for nested properties. var diff = {}; for (var key in obj1) { if (this.isFunction(obj1[key])) { continue; } var value2 = undefined; if (obj2[key] !== undefined) { value2 = obj2[key]; } diff[key] = this.map(obj1[key], value2); } // Adding properties present in obj2 but not in obj1. for (var key in obj2) { if (this.isFunction(obj2[key]) || diff[key] !== undefined) { continue; } diff[key] = this.map(undefined, obj2[key]); } return diff; }, compareValues: function (value1, value2) { // Comparison of primitive values, dates, and null. if (value1 === value2) { return this.VALUE_UNCHANGED; } if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) { return this.VALUE_UNCHANGED; } if (value1 === undefined) { return this.VALUE_CREATED; } if (value2 === undefined) { return this.VALUE_DELETED; } return this.VALUE_UPDATED; }, ...helper functions... };
この解決策を説明するために、次の 2 つのオブジェクトを考えてみましょう:
const oldObj = { a: 'i am unchanged', b: 'i am deleted', e: { a: 1, b: false, c: null }, f: [1, { a: 'same', b: [{ a: 'same' }, { d: 'delete' }] }], g: new Date('2017.11.25') }; const newObj = { a: 'i am unchanged', c: 'i am created', e: { a: '1', b: '', d: 'created' }, f: [{ a: 'same', b: [{ a: 'same' }, { c: 'create' }] }, 1], g: new Date('2017.11.25') };
深差分アルゴリズムの実行これらのオブジェクトに対して次の結果が生成されます:
{ a: { type: 'unchanged' }, b: { type: 'deleted' }, c: { type: 'created', data: 'i am created' }, e: { a: { type: 'updated', data: '1' }, b: { type: 'updated', data: '' }, c: { type: 'unchanged' }, d: { type: 'created', data: 'created' } }, f: { 0: { type: 'unchanged' }, 1: { a: { type: 'unchanged' }, b: { 0: { type: 'unchanged' }, 1: { type: 'deleted' }, 2: { type: 'created', data: { c: 'create' } } } } } }
この結果は、2 つのオブジェクト間の違いを正確にキャプチャしており、プロパティ 'b' が削除され、新しいプロパティ 'c' が作成され、' e' オブジェクトにはいくつかの更新および作成されたプロパティがあり、配列 'f' にはいくつかの変更が加えられました。
以上が一般的な深差分アルゴリズムは、ネストされたプロパティ、配列、その他の構造を持つ複雑なオブジェクト間の違いを効果的に強調表示するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。