Gav*_*cek 11 javascript recursion
问题(来自Eloquent Javascript第2版,第4章,练习4):
编写一个函数deepEqual,它接受两个值,只有当它们是相同的值时返回true,或者是与对deepEqual的递归调用相比,其值也相等的对象.
测试用例:
var obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// ? true
console.log(deepEqual(obj, {here: 1, object: 2}));
// ? false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// ? true
Run Code Online (Sandbox Code Playgroud)
我的代码:
var deepEqual = function (x, y) {
if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length)
return false;
for (var prop in x) {
if (y.hasOwnProperty(prop))
return deepEqual(x[prop], y[prop]);
/*This is most likely where my error is. The question states that all the values
should be checked via recursion; however, with the current setup, only the first
set of properties will be checked. It passes the test cases, but I would like
to solve the problem correctly!*/
}
}
else if (x !== y)
return false;
else
return true;
}
Run Code Online (Sandbox Code Playgroud)
我想我有一般的想法; 但是,就像我在评论中所说的那样,程序不会检查对象中的第二个属性.我觉得我有结构/逻辑问题而且只是以错误的方式使用递归,因为我原本打算循环遍历属性,使用递归来比较第一个属性的值,然后继续循环到下一个属性财产并再次比较.虽然,我不确定这是否可能?
我已经给出了很多想法,尝试了几种不同的方法,但这是我到目前为止最正确的答案.任何可能的提示,指出我正确的方向?
Pau*_*oub 24
正如您所怀疑的那样,您将返回所看到的第一个房产的匹配.false如果该属性不匹配,您应该返回,但请继续查看.
此外,false如果找不到任何prop属性,则返回y(即,计数匹配,但不是实际属性).
如果所有属性都匹配,则返回true:
var deepEqual = function (x, y) {
if (x === y) {
return true;
}
else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length)
return false;
for (var prop in x) {
if (y.hasOwnProperty(prop))
{
if (! deepEqual(x[prop], y[prop]))
return false;
}
else
return false;
}
return true;
}
else
return false;
}
Run Code Online (Sandbox Code Playgroud)
var deepEqual = function (x, y) {
if (x === y) {
return true;
}
else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length)
return false;
for (var prop in x) {
if (y.hasOwnProperty(prop))
{
if (! deepEqual(x[prop], y[prop]))
return false;
}
else
return false;
}
return true;
}
else
return false;
}
var obj = {here: {is: "an", other: "3"}, object: 2};
console.log(deepEqual(obj, obj));
// ? true
console.log(deepEqual(obj, {here: 1, object: 2}));
// ? false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// ? false
console.log(deepEqual(obj, {here: {is: "an", other: "2"}, object: 2}));
// ? false
console.log(deepEqual(obj, {here: {is: "an", other: "3"}, object: 2}));
// ? trueRun Code Online (Sandbox Code Playgroud)
觉得这个版本更具可读性(更容易理解)。逻辑与最佳答案非常相似。(这次是ES6)
function deepEqual(obj1, obj2) {
if(obj1 === obj2) // it's just the same object. No need to compare.
return true;
if(isPrimitive(obj1) && isPrimitive(obj2)) // compare primitives
return obj1 === obj2;
if(Object.keys(obj1).length !== Object.keys(obj2).length)
return false;
// compare objects with same number of keys
for(let key in obj1)
{
if(!(key in obj2)) return false; //other object doesn't have this prop
if(!deepEqual(obj1[key], obj2[key])) return false;
}
return true;
}
//check if value is primitive
function isPrimitive(obj)
{
return (obj !== Object(obj));
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,有一个深层骗子的作弊者版本,它就像一个符咒一样)。但是,它慢了大约1.6倍。
正如zero298所注意到的那样,这种方法对属性排序很敏感,因此不应认真对待
function cheatDeepEqual(obj1, obj2)
{
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
Run Code Online (Sandbox Code Playgroud)