2017-01-23 7 views
3

Вопрос аналогичен: How can I check that two objects have the same set of property names?, но только одна разницаJavaScript: Глубокие объекты проверки имеют одинаковые ключи

Я хочу, чтобы проверить:

var objOne = {"a":"one","b":"two","c":{"f":"three_one"}}; 
var objTwo = {"a":"four","b":"five","c":{"f":"six_one"}}; 

имеют один и тот же набор ключей на всех уровнях?

Например deepCheckObjKeys(objOne, objTwo) вернется true где deepCheckObjKeys(objOne, objThree) возвращение false, если:

var objThree = {"a":"four","b":"five","c":{"g":"six_one"}}; 

С objThree.a.c.f в objThreeundefined.

функция, как это:

'использовать строгий';

function objectsHaveSameKeys() { 
    for (var _len = arguments.length, objects = Array(_len), _key = 0; _key < _len; _key++) { 
     objects[_key] = arguments[_key]; 
    } 

    var allKeys = objects.reduce(function (keys, object) { 
     return keys.concat(Object.keys(object)); 
    }, []); 
    var union = new Set(allKeys); 
    return objects.every(function (object) { 
     return union.size === Object.keys(object).length; 
    }); 
} 

проверяет только первый уровень.

PS: objectsHaveSameKeys() ES6 эквивалент:

function objectsHaveSameKeys(...objects):boolean { 
    const allKeys = objects.reduce((keys, object) => keys.concat(Object.keys(object)), []); 
    const union = new Set(allKeys); 
    return objects.every(object => union.size === Object.keys(object).length); 
} 

ответ

4

Я бы просто сделать рекурсивную проверку, если значение свойства является объектом; см комментарии:

const deepSameKeys = (o1, o2) => { 
 
    // Get the keys of each object 
 
    const o1keys = Object.keys(o1).sort(); 
 
    const o2keys = Object.keys(o2).sort(); 
 
    // Make sure they match 
 
    // If you don't want a string check, you could do 
 
    // if (o1keys.length !== o2keys.length || !o1keys.every((key, index) => o2keys[index] === key)) { 
 
    if (o1keys.join() !== o2keys.join()) { 
 
    // This level doesn't have the same keys 
 
    return false; 
 
    } 
 
    // Check any objects 
 
    return o1keys.every(key => { 
 
    const v1 = o1[key]; 
 
    const v2 = o2[key]; 
 
    const t1 = typeof v1; 
 
    const t2 = typeof v2; 
 
    if (t1 !== t2) { 
 
     return false; 
 
    } 
 
    return t1 === "object" ? deepSameKeys(v1, v2) : true; 
 
    }); 
 
}; 
 
var objOne = {"a":"one","b":"two","c":{"f":"three_one"}}; 
 
var objTwo = {"a":"four","b":"five","c":{"f":"six_one"}}; 
 
var objThree = {"a":"four","b":"five","c":{"g":"six_one"}}; 
 

 
console.log("objOne, objTwo: " + deepSameKeys(objOne, objTwo)); 
 
console.log("objTwo, objThree: " + deepSameKeys(objTwo, objThree));

+0

Ницца. Могу ли я спросить, почему вы объявляете внутренние переменные как const, а не как var? –

+0

@ThirueswaranRajagopalan: В ES2015 и выше я по умолчанию 'const'. Я использую 'let', если мне нужно изменить значение переменной в какой-то момент, и мне не нужно было изменять их. Я вообще не использую 'var'. (Er, кроме того, я вижу, что делал это при копировании вашего objOne и такого выше. :-)) –

+0

Haaa, кажется, ваши личные предпочтения: D Cool ... –

1

Вы можете создать рекурсивную функцию, которая будет возвращать все ключи и проверить, если они равны с every().

var objOne = {"a":"one","b":"two","c":{"f":"three_one"}}; 
 
var objTwo = {"a":"four","b":"five","c":{"f":"six_one"}}; 
 

 
function checkKeys(obj1, obj2) { 
 

 
    function inner(obj) { 
 
    var result = [] 
 

 
    function rec(obj, c) { 
 
     Object.keys(obj).forEach(function(e) { 
 
     if (typeof obj[e] == 'object') rec(obj[e], c + e) 
 
     result.push(c + e) 
 
     }) 
 
    } 
 
    rec(obj, '') 
 
    return result 
 
    } 
 

 
    var keys1 = inner(obj1), keys2 = inner(obj2) 
 
    return keys1.every(e => keys2.includes(e) && keys1.length == keys2.length) 
 
} 
 

 
console.log(checkKeys(objOne, objTwo))

Смежные вопросы