skip to Main Content

Say I have the following JavaScript objects:

const obj1 = {
 key1: 'str1',
 key2: 'str2'
}

const obj2 = {
 key2: 'str2',
 key1: 'str1'
}

const obj3 = {
 key1: 'something else',
 key2: 'str2'
}

const obj4 = {
 differentKey: 'str1',
 key2: 'str2'
}

I’d like to create a unique key based on a given object. This is so I can properly cache some data related to each object. In this scenario, obj1 and obj2 should have the same key, as the only difference is the ordering of properties. obj3 and obj4 should have different keys from each other. I tried using JSON.stringify() but this gives different results for obj1 and obj2 due to the ordering. Is there a way to get around this, ideally that can work with non-primitive types?

2

Answers


  1. I think you could cast your objects to an array, sort it by keys and re-cast it to your original object type. Then you‘d have the similar order of keys and can go ahead to hashing.

    Here a more extensive answer from a similar question (not written by me)
    https://stackoverflow.com/a/1069840/20932276

    Login or Signup to reply.
  2. Here’s a function that recursively sorts nested objects by key. Then you can use JSON.stringify to create the unique keys.

    Feel free to fine tune the object type check (isObject) to fit your needs.

    function sort(object) {
      const sortedEntries = Object.entries(object).sort((a, b) =>
        a[0].localeCompare(b[0])
      );
    
      const withSortedValues = sortedEntries.map(([key, value]) => {
        const isObject = typeof value === 'object' && value !== null
        const newVal = isObject ? sort(value) : value;
        return [key, newVal];
      });
    
      return Object.fromEntries(withSortedValues);
    }
    
    function compare(obj1, obj2) {
      return JSON.stringify(sort(obj1)) === JSON.stringify(sort(obj2));
    }
    
    const obj1 = {
      a: 1,
      b: { c: 1, d: 2 },
    };
    const obj2 = {
      b: { d: 2, c: 1 },
      a: 1,
    };
    const obj3 = {
      b: { d: 4, c: 3 },
      a: 1,
    };
    
    console.log('1 == 2', compare(obj1, obj2)); // true
    console.log('1 == 3', compare(obj1, obj3)); // false
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search