我有两个对象。他们的结构看起来有点像这样:
{
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,等等。我不喜欢使用服务器端语言。
有没有办法做到这一点?
谢谢!
答案 0 :(得分:3)
JavaScript(在ES5中)有两个复合本机类型(我假设您的代码中没有任何自定义集合,如果您这样做 - 我假设它们支持'旧'迭代协议(具有.length)< / p>
以下是解决方案的注释草图。我没有运行它 - 它可以帮助您了解如何实现此算法。请注意,这会为后引用(var a = {}; a.a =a}
)输入无限循环。
function sub(big,small){
if(typeof big === "function") return small === big; // function reference equality.
if(big.length){ // iterable, for example array, nodelist etc. (even string!)
if(small.length > big.length) return false; // small is bigger!
for(var 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;
for(var key in 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])){ // doesn't have a property
return false;
}
return true;
}
}
return big === small; // primitive value type equality
// , or ES7 value type equality, future compat ftw :P
}
答案 1 :(得分:3)
只需递归检查:
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;
}
> isContainedIn(requirements, person)
true
对于更接近数组的类逻辑方法,无论顺序无关紧要,请添加类似
的内容 a.sort();
b = b.slice().sort()
(假设可订购的内容)在数组比较循环之前或用非常低效的
替换它 return a.every(function(ael) {
return b.some(function(bel) {
return isContainedIn(ael, bel);
});
});
答案 2 :(得分:0)
编辑:没有注意到merge
更改了第一个参数...更改了代码,但仍然会导致obj2更改。您可以添加_.cloneDeep(obj2)
来处理这个问题,但到那时我的解决方案似乎并不优雅。同时使用cloneDeep
更新了演示。
Edit2 :由于JSON.stringify
要求对象属性的顺序在您比较的对象中相同,因此您可以使用Object comparison in JavaScript之类的内容。但是,在演示中,您可以看到它有效,所以我想很有可能对于您的情况,使用_.merge
和JSON.stringify
是可靠的。
使用lo-dash,您可以使用_.merge
并检查结果是否与较大的对象相同。
function(obj1, obj2) {
var obj3 =_.merge(_.cloneDeep(obj2), obj1);
return JSON.stringify(obj3) === JSON.stringify(obj1);
}
当然,另一种选择是用vanilla JS迭代整个对象。
答案 3 :(得分:0)
//当对象的顺序不相同时
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
答案 4 :(得分:0)
除了本杰明的答案-您还可以对此进行测试:
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
};
,甚至使用更清洁的解决方案: https://github.com/blackflux/object-deep-contain