gpt4 book ai didi

javascript - 比较JavaScript中的循环(自引用)对象

转载 作者:行者123 更新时间:2023-11-29 17:36:25 24 4
gpt4 key购买 nike

我正在比较两个包含stringnumberarrayobject值的对象。至此没有问题。当我尝试比较自引用对象时,出现以下错误RangeError: Maximum call stack size exceeded。如果自引用对象被引用到另一个对象的相同级别,则应将它们视为相等。我的问题是如何实现。这是我的代码:

const equalsComplex = function(value, other) {
// Get the value type
const type = Object.prototype.toString.call(value);

// If the two objects are not the same type, return false
if (type !== Object.prototype.toString.call(other)) return false;

// If items are not an object or array, return false
if (['[object Array]', '[object Object]'].indexOf(type) < 0) return false;

// Compare the length of the length of the two items
const valueLen =
type === '[object Array]' ? value.length : Object.keys(value).length;
const otherLen =
type === '[object Array]' ? other.length : Object.keys(other).length;
if (valueLen !== otherLen) return false;

// Compare two items
const compare = function(item1, item2) {
// Get the object type
const itemType = Object.prototype.toString.call(item1);

// If an object or array, compare recursively
if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) {
if (!equalsComplex(item1, item2)) return false;
}

// Otherwise, do a simple comparison
else {
// If the two items are not the same type, return false
if (itemType !== Object.prototype.toString.call(item2)) return false;

// Else if it's a function, convert to a string and compare
// Otherwise, just compare
if (itemType === '[object Function]') {
if (item1.toString() !== item2.toString()) return false;
} else {
if (item1 !== item2) return false;
}
}
};

// Compare properties
if (type === '[object Array]') {
for (let i = 0; i < valueLen; i++) {
if (compare(value[i], other[i]) === false) return false;
}
} else {
for (let key in value) {
if (value.hasOwnProperty(key)) {
if (compare(value[key], other[key]) === false) return false;
}
}
}

// If nothing failed, return true
return true;
};
const r = { a: 1 };
r.b = r;
const d = { a: 1 };
d.b = d;

console.log(
equalsComplex(
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
},
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
}
)
);

最佳答案

我喜欢@stevendesu的回复。他很好地解决了圆形结构的问题。我使用您的代码编写了一个解决方案,该解决方案也可能会有所帮助。

const equalsComplex = function(value, other, valueRefs, otherRefs) {
valueRefs = valueRefs || [];
otherRefs = otherRefs || [];

// Get the value type
const type = Object.prototype.toString.call(value);

// If the two objects are not the same type, return false
if (type !== Object.prototype.toString.call(other)) return false;

// If items are not an object or array, return false
if (['[object Array]', '[object Object]'].indexOf(type) < 0) return false;

// We know that the items are objects or arrays, so let's check if we've seen this reference before.
// If so, it's a circular reference so we know that the branches match. If both circular references
// are in the same index of the list then they are equal.
valueRefIndex = valueRefs.indexOf(value);
otherRefIndex = otherRefs.indexOf(other);
if (valueRefIndex == otherRefIndex && valueRefIndex >= 0) return true;
// Add the references into the list
valueRefs.push(value);
otherRefs.push(other);

// Compare the length of the length of the two items
const valueLen =
type === '[object Array]' ? value.length : Object.keys(value).length;
const otherLen =
type === '[object Array]' ? other.length : Object.keys(other).length;
if (valueLen !== otherLen) return false;

// Compare two items
const compare = function(item1, item2) {
// Get the object type
const itemType = Object.prototype.toString.call(item1);

// If an object or array, compare recursively
if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) {
if (!equalsComplex(item1, item2, valueRefs.slice(), otherRefs.slice())) return false;
}

// Otherwise, do a simple comparison
else {
// If the two items are not the same type, return false
if (itemType !== Object.prototype.toString.call(item2)) return false;

// Else if it's a function, convert to a string and compare
// Otherwise, just compare
if (itemType === '[object Function]') {
if (item1.toString() !== item2.toString()) return false;
} else {
if (item1 !== item2) return false;
}
}
};

// Compare properties
if (type === '[object Array]') {
for (let i = 0; i < valueLen; i++) {
if (compare(value[i], other[i]) === false) return false;
}
} else {
for (let key in value) {
if (value.hasOwnProperty(key)) {
if (compare(value[key], other[key]) === false) return false;
}
}
}

// If nothing failed, return true
return true;
};
const r = { a: 1 };
r.b = {c: r};
const d = { a: 1 };
d.b = {c: d};

console.log(
equalsComplex(
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
},
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
d
]
}
)
);

基本上,您要跟踪到目前为止在每个分支中看到的对对象和数组的引用(slice()方法对引用数组进行浅拷贝)。然后,每次看到对象或数组时,都要检查引用历史,以查看它是否为循环引用。如果是这样,请确保两个循环引用都指向历史的同一部分(这很重要,因为两个循环引用都可能指向对象结构中的不同位置)。

我建议对此使用库,因为我还没有对代码进行深入测试,但是有一个简单的解决方案可供您使用。

关于javascript - 比较JavaScript中的循环(自引用)对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56048142/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com