Digamos que tengo dos objetos, que pueden tener algunas propiedades en común. La idea general es que uno se usa como esquema para compararlo con el otro. Me gustaría comparar valores de propiedades comunes y construir un nuevo objeto que represente estas comparaciones de cada propiedad individual. En el resultado, cualquier propiedad en común debe tener el valor de comparar las propiedades de origen para la igualdad (por ejemplo result.abc = (obj1.abc == obj2.abc) ). Cualquier propiedad que exista en solo uno de los dos objetos se copiaría en el resultado con sus valores originales.
Por ejemplo, considere los siguientes objetos para comparar:
const schema = { num: 123, str: 'hello', nested: { num: 123, str: 'hello', }, }, doc = { nums: [1,2,3], str: 'hello', nested: { num: 123, str: 'world', foo: 'bar', }, };El resultado de la comparación debe ser:
{ nums: [1,2,3], // obj2.nums num: 123, // obj1.num str: true, // obj1.str == obj2.str nested: { num: true, // obj1.nested.num == obj2.nested.num str: false, // obj1.nested.str == obj2.nested.str foo: 'bar', // obj2.nested.foo }, }¿Cómo realizaría esta comparación de la manera más eficiente en tiempo y espacio?
Actualmente tengo esta implementación:
function deepCompare(obj1, obj2) { const validatedObject = {} Object.keys(obj1).forEach(e => { if(object[e].constructor.name === 'Object') { validatedObject[e] = deepCompare(obj1[e], obj2[e]) } else { validatedObject[e] = obj1[e] === obj2[e] } }) return validatedObject } ¿Hay alguna forma de hacer esto de manera más eficiente sin usar JSON.stringify , porque es posible que falte una propiedad, pero aún quiero devolver el hecho de que los values son correctos a pesar del esquema de esos objetos?
¿Quizás for in o for of loop? Pero, ¿cómo probaría su eficacia? Está bien para objetos pequeños, pero a veces se vuelven muy grandes y quiero compararlos de la manera más eficiente posible.
NOTA para los editores.
Entiendo que esto puede parecer un duplicado, pero de hecho no lo es, aquí estoy buscando una forma más eficiente de comparar valores , de forma iterativa, recursiva o de alguna otra manera, no los objetos en sí .
la lógica es si
obj1tiene una clave yobj2tiene la misma clave, comparamos los valores de esas claves
Entonces deberías usar
function compare(a, b) { if (a === b) return true; if (typeof a == 'object' && a != null && typeof b == 'object' && b != null) { return Object.keys(a).every(k => !(k in b) || compare(a[k], b[k]) ); } return false; }Creo que su solución es lo suficientemente buena, solo le faltan algunas comprobaciones predeterminadas (no necesita iterar a través de las claves de objetos si tiene la misma referencia, por ejemplo).
Además, existe este paquete que afirma ser el comprobador de igualdad profundo más rápido.
Puede revisar el código para ver si se saltó alguna otra condición (todavía es una solución recursiva para los objetos, pero hay otros tipos de datos tratados allí si está interesado).
También existe este artículo si prefiere material escrito en lugar de código que tiene más comprobaciones antes de las llamadas recursivas.
Lo que quiere hacer es primero encontrar las claves de objeto comunes. Luego, a medida que recorre las propiedades, desea devolver falso tan pronto como encuentre una falta de coincidencia. En el fragmento a continuación, estoy usando un bucle every que se detendrá tan pronto como una iteración devuelva false . Si devuelve un valor en el bloque if , no necesita el bloque else .
function deepCompare(obj1, obj2) { const commonKeys = Object.keys(obj1).filter(x => Object.keys(obj2).includes(x)); let valid = true; commonKeys.every(e => { if (obj1[e].constructor.name === 'Object') { console.log('object', e, obj1[e], obj2[e]) valid = deepCompare(obj1[e], obj2[e]) return valid // true goes to next, false ends the .every loop } console.log('not object', e, obj1[e] === obj2[e] ? 'match' : 'mismatch') valid = obj1[e] === obj2[e] return valid // true goes to next, false ends the .every loop }) return valid // returns the first false or true if everything passes } const obj1 = { num: 123, str: 'hello', nested: { num: 123, str: 'hello', } } const obj3 = { num: 1233, str: 'hello' } const obj4 = { num: 123, str: 'hello', nested: { num: 123, str: 'hellure', } } console.log(deepCompare(obj1, obj1.nested)) console.log(deepCompare(obj1, obj3)) console.log(deepCompare(obj1, obj4))