Home > Web Front-end > JS Tutorial > How can a generic deep diff algorithm effectively highlight differences between complex objects with nested properties, arrays, and other structures?

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

Susan Sarandon
Release: 2024-11-23 09:19:28
Original
849 people have browsed it

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

Generic Deep Diff Between Two Objects

In software development, it often becomes necessary to determine the differences between two objects. This can be a straightforward process when working with primitive data types, but becomes more complicated when dealing with deep objects containing nested properties, arrays, and other complex structures.

Implementation Details

I recently encountered this challenge and found that a generic deep diff algorithm was the most effective approach. This involves recursively traversing both objects, comparing their values, and generating a result object that represents the differences.

To achieve this, I developed the following solution:

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...
};
Copy after login

Example Usage

To illustrate this solution, consider the following two objects:

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')
};
Copy after login

Running the deep diff algorithm on these objects will produce the following result:

{
  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' } }
      }
    }
  }
}
Copy after login

This result accurately captures the differences between the two objects, indicating that the property 'b' was deleted, a new property 'c' was created, the 'e' object had several updated and created properties, and the array 'f' underwent some changes.

The above is the detailed content of How can a generic deep diff algorithm effectively highlight differences between complex objects with nested properties, arrays, and other structures?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template