一般的な深差分アルゴリズムは、ネストされたプロパティ、配列、その他の構造を持つ複雑なオブジェクト間の違いを効果的に強調表示するにはどうすればよいでしょうか?

Susan Sarandon
リリース: 2024-11-23 09:19:28
オリジナル
767 人が閲覧しました

How can a generic deep diff algorithm effectively highlight differences between complex objects with nested properties, arrays, and other structures?

2 つのオブジェクト間の一般的な深い差分

ソフトウェア開発では、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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート