20

I want to compare two Json object arrays. One has more data. For the final result if one id finds another the selected checkbox = true. So far there are 4 and it only finds one. Do I loop through the long array first and then loop through the second array to find a match?

 this.formAll = JSON.parse(response)
      for (var i = 0; i < this.formAll.length; i++) {
        for (var j = i; j <  this.formAb.length; j++) {
         console.log( this.formAb[j].id,  this.formAll[i].SeriesNumber);
          if ( this.formAll[i].id === this.formAb[j].id) {
            console.log( 'small=', this.formAb[j].id, 'large=', 
         this.formAll[i].id );
         this.formAll[i].selected = true;
        }}
      }
0

9 Answers 9

43

Fast and limited

JSON.stringify(obj1) === JSON.stringify(obj2)

Slow and more generic

Object.equals = function( x, y ) {
    if ( x === y ) return true;
    // if both x and y are null or undefined and exactly the same

    if ( ! ( x instanceof Object ) || ! ( y instanceof Object ) ) return false;
    // if they are not strictly equal, they both need to be Objects

    if ( x.constructor !== y.constructor ) return false;
    // they must have the exact same prototype chain, the closest we can do is
    // test there constructor.

    for ( var p in x ) {
        if ( ! x.hasOwnProperty( p ) ) continue;
        // other properties were tested using x.constructor === y.constructor

       if ( ! y.hasOwnProperty( p ) ) return false;
       // allows to compare x[ p ] and y[ p ] when set to undefined

       if ( x[ p ] === y[ p ] ) continue;
       // if they have the same strict value or identity then they are equal

       if ( typeof( x[ p ] ) !== "object" ) return false;
       // Numbers, Strings, Functions, Booleans must be strictly equal

       if ( ! Object.equals( x[ p ],  y[ p ] ) ) return false;
       // Objects and Arrays must be tested recursively
   }

   for ( p in y ) {
      if ( y.hasOwnProperty( p ) && ! x.hasOwnProperty( p ) ) return false;
      // allows x[ p ] to be set to undefined
    }
    return true;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Do not add properties onto built-in runtime entities. This property may become a standard in the future, not necessarily implemented the same way.
JSON.stringify(obj1) === JSON.stringify(obj2) I believe this will work if the properties are ordered the same though this may not always be the case.
21

In Javascript/Typescript (If order of keys of both the objects are same) : Use

  1. JSON.stringify(obj1) === JSON.stringify(obj2)
  2. Object.entries(obj1).toString() === Object.entries(obj2).toString()

obj1 = { a:1, b:2 } obj2 = { a:1, b:2 } // true

obj1 = { a:1, b:2 } obj2 = { b:2, a:1 } // false

  1. Using Lodash , irrespective of key's order

    _.isEqual(obj1 , obj2 ); // true

  2. Compare each keys of object individually

Comments

6

For Angular use Deep Equal

import * as deepEqual from "deep-equal";

console.log(deepEqual({a:123},{a:123})); // True

1 Comment

Beware. deepEqual is replaced by deepStrictEqual and the return type is not bool but an asswerts like so: function deepStrictEqual<T>(actual: any, expected: T, message?: string | Error): asserts actual is T; Read more about asserts here: typescriptlang.org/docs/handbook/release-notes/…
2

My suggestion is to compare the objects' fields one by one:

  private compareTwoObjects(object1: any, object2: any): boolean {
    let compareRes = true;
    if (Object.keys(object1).length === Object.keys(object2).length) {
      Object.keys(object1).forEach(key => {
        if (object1[key] !== object2[key]) {
          compareRes = false;
        }
      });
    } else {
      compareRes = false;
    }
    return compareRes;
  }

Comments

0

You can achieve the result using the for-of and find method like :

for(let item  of this.formAll) {
    if (this.formAb.find((i) => { i.id === item.id})){
       item.selected = true;
    }
}

1 Comment

What if I don't know what properties the object has but still want to compare them?
0

this worked out better using filter.

   this.formAll = JSON.parse(response)
    this.formAll.forEach((element) => {
      this.formAb.filter((element1) => {
        if (element1.id === element.id ) {
          element.selected = true;
        }
     })
     })

Comments

0

Compare two Json Objects togather Example : obj 1 :

{
id : 1,
name : 'HADY',
status : false
}

obj 2 :

{
id : 1,
name : 'example',
surename : 'example',
nickname : 'example'
status : true
}

------------------------------------------------compare(obj1, obj2) {

  const keys1 = [];
    const values1 = [];
    Object.keys(obj1).forEach((element) => {
      keys1.push(element);
    });
    Object.values(obj1).forEach((element) => {
      values1.push(element);
    });
    const keys2 = [];
    const values2 = [];
    Object.keys(obj2).forEach((element) => {
      keys2.push(element);
    });
    Object.values(obj2).forEach((element) => {
      values2.push(element);
    });
    const obj = {};
    keys1.forEach((element, i) => {
      for (let index = 0; index < keys2.length; index++) {
        if (element === keys2[index]) {
          if (values1[i] !== values2[index]) {
            const jsonKey = element;
            obj[jsonKey] = values1[i];
          }
          break;
        }
      }
    });
    console.log(obj);
    return obj;
  }

it will return the deference only : obj

{
name : 'HADY',
status : false
}

Comments

0

I think compare "JSON.Stringify" method doesn't correct; Next Variant with checking recursive objects also:

interface IComparator<T> {
  equals(obj: T, other: T): boolean;
}

export default class Comparator<T> implements IComparator<T> {
  equals(item: T, otherItem: T): boolean {
    if (typeof item !== typeof otherItem) {
      return false;
    }

    const objectCache: any[] = [];
    const otherObjectCache: any[] = [];
    const getIndexFromCache = (compareObject: any, cacheArray: any[]): number =>
      cacheArray.findIndex((item) => item === compareObject);

    switch (true) {
      case item === otherItem:
        return true;
      case typeof item !== 'object':
        return item === otherItem;
      case item === null || otherItem === null:
        return item === null && otherItem === null;
      case Object.keys(item).length !== Object.keys(otherItem).length:
        return false;
      default:
        const object = item as any;
        const otherObject = otherItem as any;

        return Object.keys(object).every((key: string) => {
          const hasKeyInOtherObject = Object.prototype.hasOwnProperty.call(otherItem, key);

          if (!hasKeyInOtherObject) {
            return false;
          }

          const cacheObjectIndex = getIndexFromCache(object[key], objectCache);
          const cacheOtherObjectIndex = getIndexFromCache(otherObject[key], otherObjectCache);

          if (cacheObjectIndex !== cacheOtherObjectIndex) {
            return false;
          }

          const isEqualsCacheObjects =
            cacheObjectIndex !== -1 && cacheOtherObjectIndex !== -1 && cacheObjectIndex === cacheOtherObjectIndex;

          if (isEqualsCacheObjects) {
            return true;
          }

          objectCache.push(object[key]);
          otherObjectCache.push(otherObject[key]);

          return new Comparator<any>().equals(object[key], otherObject[key]);
        });
    }
  }
}

and test with jest for it:

import Comparator from './Comparator';

export default describe('Comparator', () => {
  const recursiveA: { value: number; b?: any } = { value: 1 };
  const recursiveB: { value: number; a?: any } = { value: 2 };

  recursiveA.b = recursiveB;
  recursiveB.a = recursiveA;

  it.each([
    [null, null, true],
    [undefined, undefined, true],
    [1, 1, true],
    ['test', 'test', true],
    [[1, 2], [1, 2], true],
    [{ a: 1, b: 3 }, { a: 1, b: 3 }, true],
    [2, 1, false],
    ['test', 'test2', false],
    [[1, 2], [2, 1], false],
    [{ a: 1, b: 3 }, { a: 3, b: 1 }, false],
    [recursiveA, recursiveB, false],
    [null, 1, false],
    [null, {}, false],
    [undefined, null, false],
    [1, '1', false],
  ])('compares values %o and %o are equal: %s', (value1: any, value2: any, expectedResult: boolean) => {
    const comparator = new Comparator<any>();
    const actualResult = comparator.equals(value1, value2);

    expect<boolean>(actualResult).toBe(expectedResult);
  });
});

And Javascript version:

export default class Comparator {
    equals(item, otherItem) {
        if (typeof item !== typeof otherItem) {
            return false;
        }

        const objectCache = [];
        const otherObjectCache = [];
        const getIndexFromCache = (compareObject, cacheArray) => cacheArray.findIndex((item) => item === compareObject);

        switch (true) {
            case item === otherItem:
                return true;
            case typeof item !== 'object':
                return item === otherItem;
            case item === null || otherItem === null:
                return item === null && otherItem === null;
            case Object.keys(item).length !== Object.keys(otherItem).length:
                return false;
            default:
                const object = item;
                const otherObject = otherItem;

                return Object.keys(object).every((key) => {
                    const hasKeyInOtherObject = Object.prototype.hasOwnProperty.call(otherItem, key);

                    if (!hasKeyInOtherObject) {
                        return false;
                    }

                    const cacheObjectIndex = getIndexFromCache(object[key], objectCache);
                    const cacheOtherObjectIndex = getIndexFromCache(otherObject[key], otherObjectCache);

                    if (cacheObjectIndex !== cacheOtherObjectIndex) {
                        return false;
                    }

                    const isEqualsCacheObjects = cacheObjectIndex !== -1 && cacheOtherObjectIndex !== -1 && cacheObjectIndex === cacheOtherObjectIndex;

                    if (isEqualsCacheObjects) {
                        return true;
                    }

                    objectCache.push(object[key]);
                    otherObjectCache.push(otherObject[key]);

                    return new Comparator().equals(object[key], otherObject[key]);
                });
        }
    }
}

Comments

-1

GO EASY AND SIMPLE!!

If object keys are the same and in order, JSON.stringify(Obj2) works the quickest:

Obj1 = { fruit: '🥝' };
Obj2 = { fruit: '🥝' };

JSON.stringify(Obj1) === JSON.stringify(Obj2);

4 Comments

This answer has already been given, try to explain more or this answer will not be helpfull.
This isn't always the case. If you stringify two objects, the order in the properties might not necessarily be in the same order, meaning the two strings will differ greatly
@JohanAspeling, that's what is said above. "If object keys are the same and in order..."
But you cant know if they will be in the same order...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.