skip to Main Content

I’m attempting to get the keys from an object comparison. If the comparison finds a different object, it should return the key that has to be updated, This is the object:

{
  "crm": "",
  "dateReceita": "2023-07-27T03:00:00.000Z",
  "imagens": [
    {
      "extension": "jpeg",
      "url": "https://firebasestorage.jhsCYMi9l0Zgcw1%2F29544f6b-caec-4e42-93ae-3b4f3f9a854a.jpeg?alt=media&token=78e"
    }
  ],
  "laboratorio": "",
  "lotes": [
    {
      "lote": "LOte0",
      "loteQtd": "8"
    },
    {
      "lote": "Lote 2",
      "loteQtd": "2"
    }
  ],
  "nome": "Lotes",
  "produto": "Dem",
  "quantidade": 10,
  "tipo": "Branca",
  "vendida": true
}

This is the function I’m runnig:

const getNew = (newObj, oldObj) => {
    if (Object.keys(oldObj).length == 0 && Object.keys(newObj).length > 0)
      return newObj

    const diff = {}
    for (const key in oldObj) {
      if (newObj[key] && oldObj[key] != newObj[key]) {
        diff[key] = newObj[key]
      }
    }

    if (Object.keys(diff).length > 0) return diff

    return oldObj
  }

Although if I compare that object with itself, it always shows that imagens and lotes have some different data, even though it does not

3

Answers


  1. function findUpdatedKeys(originalObj, updatedObj) {
      const updatedKeys = {};
    
        for (const key in originalObj) {
          if (originalObj.hasOwnProperty(key)) {
            if (!updatedObj.hasOwnProperty(key) || originalObj[key] !== updatedObj[key]) {
              updatedKeys[key] = updatedObj[key];
            }
          }
        }
    
        return updatedKeys;
    }
    const originalObject = {
      name: 'John Doe',
      age: 30,
      email: '[email protected]',
    };
    
    const updatedObject = {
      name: 'Jane Doe',
      age: 31,
      email: '[email protected]',
    };
    
    const updatedKeys = findUpdatedKeys(originalObject, updatedObject);
    console.log(updatedKeys);
    Login or Signup to reply.
  2. Its very important in high level languages to understand which types are reference type and which types are value type.
    For value types, value is compared for equality, for reference types, the reference (memory address) is compared for equality. The reference is the address in memory. So if two reference types are compared for equality, if they are different instances, they will have a different memory address and they will be different.
    In your case you are obtaining imagens and lotes because an array is a reference type. If those are different array instances, they are not equal according to == or ===.

    For that you need a function that compares the values for you as the one below. Libraries do this for you also as mentioned in the comments.

    const myObj = {
        "crm": "",
        "dateReceita": "2023-07-27T03:00:00.000Z",
        "imagens": [
          {
            "extension": "jpeg",
            "url": "https://firebasestorage.jhsCYMi9l0Zgcw1%2F29544f6b-caec-4e42-93ae-3b4f3f9a854a.jpeg?alt=media&token=78e"
          }
        ],
        "laboratorio": "",
        "lotes": [
          {
            "lote": "LOte0",
            "loteQtd": "8"
          },
          {
            "lote": "Lote 2",
            "loteQtd": "2"
          }
        ],
        "nome": "Lotes",
        "produto": "Dem",
        "quantidade": 10,
        "tipo": "Branca",
        "vendida": true
      }
    
      const myObj2 = {
        "crm": "",
        "dateReceita": "2023-07-27T03:00:00.000Z",
        "imagens": [
          {
            "extension": "jpeg",
            "url": "https://firebasestorage.jhsCYMi9l0Zgcw1%2F29544f6b-caec-4e42-93ae-3b4f3f9a854a.jpeg?alt=media&token=78e",
            "what":'wat'
          }
        ],
        "laboratorio": "",
        "lotes": [
          {
            "lote": "LOte0",
            "loteQtd": "8"
          },
          {
            "lote": "Lote 2",
            "loteQtd": "2"
          }
        ],
        "nome": "Lotes",
        "produto": "Dem",
        "quantidade": 10,
        "tipo": "Branca",
        "vendida": true
      }
    
      function isObjArrayValueEqual(arr1, arr2) {
        // Check if both arguments are arrays
        if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
          return false;
        }
      
        // Check if both arrays have the same length
        if (arr1.length !== arr2.length) {
          return false;
        }
      
        // Compare each object in the arrays
        for (let i = 0; i < arr1.length; i++) {
          const obj1 = arr1[i];
          const obj2 = arr2[i];
      
          // Check if both elements are objects
          if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
            return false;
          }
      
          // Get the keys of each object
          const keys1 = Object.keys(obj1);
          const keys2 = Object.keys(obj2);
      
          // Check if both objects have the same number of properties
          if (keys1.length !== keys2.length) {
            return false;
          }
      
          // Compare the values of each property in the objects
          for (const key of keys1) {
            if (obj1[key] !== obj2[key]) {
              return false;
            }
          }
        }
      
        // If all comparisons pass, the arrays are equal
        return true;
      }
    
      const getNew = (newObj, oldObj) => {
        if (Object.keys(oldObj).length == 0 && Object.keys(newObj).length > 0)
          return newObj
    
        const diff = {}
        for (const key in oldObj) {
          if (newObj[key] && (oldObj[key] !== newObj[key])) {
            if (Array.isArray(newObj[key])) {
                if (!isObjArrayValueEqual(newObj[key], oldObj[key])) {
                    diff[key] = newObj[key]        
                }
            } else {
                diff[key] = newObj[key]
            }
            
          }
        }
    
        if (Object.keys(diff).length > 0) return diff
    
        return diff
      }
    
      console.log(getNew(myObj, myObj2))

    If you have other reference types in your object that are not arrays and are reference types, you would need to use a value compare function (of your own or from a library) to check for value equality.

    Login or Signup to reply.
  3. Lotes and imagens are also objects so the == or != operators won’t give you the desired result. You’ll need to modify your function to check if the keys hold values that are objects and call it recursively, making your function capable of comparing objects deeply.
    Here’s an idea to help you out.

    // create a function to be used for comparing objects
    function compareObjects(difference, oldObj, newObj) {
       for (const key of oldObj) {
          if (newObj[key]) {
              // the new object has that key
                  if (typeof key == "object" && typeof key == "object") {
              // if they are both objects, call the function again with the keys as arguments
                  compareObjects(difference[key], oldObj[key], newObj[key])
              //skip the rest of this iteration
                  continue
              }
              // if they keys aren't objects
              if (oldObj[key] != newObj[key]) {
                 difference[key] = newObj[key]
              }
           }
        }
    }
    
    const getNew = (newObj, oldObj) => {
        if (Object.keys(oldObj).length == 0 && Object.keys(newObj).length > 0)
          return newObj
    
        const diff = {}
        compareObjects(diff, oldObj, newObj)
    
        if (Object.keys(diff).length > 0) return diff
    
        return oldObj
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search