Javascript 对象比较:检查一个对象是否包含整个其他对象
我有两个目标。它们的结构看起来有点像这样:Javascript 对象比较:检查一个对象是否包含整个其他对象,javascript,Javascript,我有两个目标。它们的结构看起来有点像这样: { education: ["school", "institute"], courses: ["HTML", "JS", "CSS"], Computer: { "OS":"WXP", "WS":"NotePad" } } 第二点: { education: ["school", "university", "institute", "collage"], courses: ["HTML
{
education: ["school", "institute"],
courses: ["HTML", "JS", "CSS"],
Computer: {
"OS":"WXP",
"WS":"NotePad"
}
}
第二点:
{
education: ["school", "university", "institute", "collage"],
courses: ["HTML", "CSS", "JS", "Managing", "Directing"],
Computer: {
"OS":"WXP",
"WS":"NotePad",
"AV":"Avast"
},
something: function(){...},
other: "thing"
}
您可能注意到,第二个对象包含整个第一个对象,以及第一个对象没有的一些项目。我需要比较这两个对象,如果第二个对象包含第一个对象的每一项,我需要得到一个答案(
true
-false
)
true
-如果第一个对象的所有项目也在第二个对象中false
-如果第一个对象的至少一个项目不在第二个对象中,例如:如果第二个对象没有“css”课程
(第一个是要求,第二个是该人员所拥有的。我需要检查该人员是否具备所有要求)
可以是普通的JS、jQuery等等。我不喜欢使用服务器端语言
有办法吗
谢谢 Edit:没有注意到
merge
更改了第一个参数。。。更改了代码,但仍会导致obj2更改。您可以添加。.cloneDeep(obj2)
,这应该可以解决这个问题,但到那时,我的解决方案似乎并不那么优雅。还使用cloneDeep
更新了演示
Edit2:由于JSON.stringify
要求比较对象中的对象属性顺序相同,因此可以使用类似的命令。但是,在演示中,您可以看到它是有效的,因此我想说,对于您的情况,使用\uuu.merge
和JSON.stringify
是可靠的
使用,您可以使用\合并,并检查结果是否与较大的对象相同
function(obj1, obj2) {
var obj3 =_.merge(_.cloneDeep(obj2), obj1);
return JSON.stringify(obj3) === JSON.stringify(obj1);
}
当然,另一种选择是使用vanilla JS迭代整个对象。JavaScript(在ES5中)有两种复合本机类型(我假设您的代码中没有任何自定义集合,如果有-我假设它们支持“旧”迭代协议(具有.length)
这是一个带注释的解决方案草图。我运行它不是为了让您了解如何实现此算法。请注意,这会进入一个无休止的反向引用循环(var a={};a.a=a}
)
功能子模块(大、小){
if(typeof big==“function”)返回small==big;//函数引用相等。
if(big.length){//iterable,例如数组、节点列表等(偶数字符串!)
如果(small.length>big.length)返回false;//small越大!
对于(变量i=0;i
只需递归检查:
function isContainedIn(a, b) {
if (typeof a != typeof b)
return false;
if (Array.isArray(a) && Array.isArray(b)) {
// assuming same order at least
for (var i=0, j=0, la=a.length, lb=b.length; i<la && j<lb;j++)
if (isContainedIn(a[i], b[j]))
i++;
return i==la;
} else if (Object(a) === a) {
for (var p in a)
if (!(p in b && isContainedIn(a[p], b[p])))
return false;
return true;
} else
return a === b;
}
对于更像集合逻辑的数组方法,顺序无关紧要,添加如下内容
a.sort();
b = b.slice().sort()
(假设可订购的内容)在数组比较循环之前,或者用非常低效的
return a.every(function(ael) {
return b.some(function(bel) {
return isContainedIn(ael, bel);
});
});
//当对象的顺序不同时
function isContainedIn(a, b) {
if (typeof a != typeof b)
return false;
if (Array.isArray(a) && Array.isArray(b)) {
if(a.length == 1) {
var j=0;
while (j < b.length) {
if ((isContainedIn( a[0], b[j]))) {
return true;
}
j++;
}
return false;
} else {
var k=0;
while (k < a.length) {
if (!(isContainedIn([a[k]], b))) {
return false;
}
k++;
}
return true;
}
} else if (Object(a) === a) {
for (var p in a)
if (!(p in b && isContainedIn(a[p], b[p])))
return false;
return true;
} else
return a === b;
};
isContainedIn(requirements, person)
true
函数包含在(a,b)中{
if(a的类型!=b的类型)
返回false;
if(Array.isArray(a)和&Array.isArray(b)){
如果(a.length==1){
var j=0;
而(j
除了Benjamin的答案之外,您还可以测试:
const sub = (big, small) => {
if (typeof big === 'function' || typeof small === 'string') return small === big; // function or string reference equality
if (big && big.length) { // iterable, for example array, nodelist etc. (even string!)
if (small.length > big.length) return false; // small is bigger!
for (let i = 0; i < small.length; i++)
if (!sub(big[i], small[i])) // doesn't have a property
return false;
return true; // all properties are subproperties recursively
}
if (typeof big === 'object' && big !== null) {
// I assume null is not a subset of an object, you may change this, it's conceptual
if (typeof small !== 'object' || small === null) return false;
// console.log(Object.keys(small));
for (const key of Object.keys(small)) {
// I consider the prototype a part of the object, you may filter this with a
// hasOwnProperty check here.
if (sub(big[key], small[key]) === false) // doesn't have a property
return false;
continue;
}
return true;
}
return big === small; // primitive value type equality
};
const sub=(大,小)=>{
if(typeof big=='function'| | typeof small=='string')返回small=='big;//函数或字符串引用相等
if(big&&big.length){//iterable,例如数组、节点列表等(偶数字符串!)
如果(small.length>big.length)返回false;//small越大!
for(设i=0;ifunction isContainedIn(a, b) {
if (typeof a != typeof b)
return false;
if (Array.isArray(a) && Array.isArray(b)) {
if(a.length == 1) {
var j=0;
while (j < b.length) {
if ((isContainedIn( a[0], b[j]))) {
return true;
}
j++;
}
return false;
} else {
var k=0;
while (k < a.length) {
if (!(isContainedIn([a[k]], b))) {
return false;
}
k++;
}
return true;
}
} else if (Object(a) === a) {
for (var p in a)
if (!(p in b && isContainedIn(a[p], b[p])))
return false;
return true;
} else
return a === b;
};
isContainedIn(requirements, person)
true
const sub = (big, small) => {
if (typeof big === 'function' || typeof small === 'string') return small === big; // function or string reference equality
if (big && big.length) { // iterable, for example array, nodelist etc. (even string!)
if (small.length > big.length) return false; // small is bigger!
for (let i = 0; i < small.length; i++)
if (!sub(big[i], small[i])) // doesn't have a property
return false;
return true; // all properties are subproperties recursively
}
if (typeof big === 'object' && big !== null) {
// I assume null is not a subset of an object, you may change this, it's conceptual
if (typeof small !== 'object' || small === null) return false;
// console.log(Object.keys(small));
for (const key of Object.keys(small)) {
// I consider the prototype a part of the object, you may filter this with a
// hasOwnProperty check here.
if (sub(big[key], small[key]) === false) // doesn't have a property
return false;
continue;
}
return true;
}
return big === small; // primitive value type equality
};