查找一个对象是否是 javascript 中另一个对象的子集

Find if an object is subset of another object in javascript

本文关键字:一个对象 子集 javascript 是否是 查找      更新时间:2023-09-26

我需要一个函数isSubset,当给定两个对象时,它会比较其值并判断一个对象是否是另一个对象的子集。

object1 = { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }};
object2 = { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }};
isSubset(object1, object2); //should return true
object3 = { pickUpLocation : {city : 'Chennai', state: 'Telangana' }}
object4 = { dist : 322, pickUpLocation: {city : 'Hyderabad', state: 'Telangana' }}
isSubset(object3, object4) //should return false as city's value is different

使用 Lodash isMatch

_.isMatch({prop: 'object', id: 3}, {prop: 'object'})

在对象和源之间执行部分深度比较,以确定对象是否包含等效的属性值。

有点晚了,但它可能会帮助人们在不使用任何外部库的情况下寻找答案。

isSubset = (superObj, subObj) => {
    return Object.keys(subObj).every(ele => {
        if (typeof subObj[ele] == 'object') {
            return isSubset(superObj[ele], subObj[ele]);
        }
        return subObj[ele] === superObj[ele]
    });
};
let object1 = { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }};
let object2 = { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }};
console.log(isSubset(object2, object1));
let object3 = { pickUpLocation : {city : 'Chennai', state: 'Telangana' }}
let object4 = { dist : 322, pickUpLocation: {city : 'Hyderabad', state: 'Telangana' }}
console.log(isSubset(object4, object3));

它可以很容易地用lodash完成。

import _ from 'lodash'
const isSubset = (aSubset, aSuperset) => (
    _.every(aSubset, (val, key) => _.isEqual(val, aSuperset[key]))
)

用法:

const object1 = { pickUpLocation: { city: 'Hyderabad', state: 'Telangana' }}
const object2 = { dist: 322, pickUpLocation:  { city: 'Hyderabad', state: 'Telangana' }}
isSubset(object1, object2)

您可以尝试使用 isSubset 包。

这是真的

isSubset(
  { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }},
  { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }}
);

这是错误的

isSubset(
  { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }},
  { pickUpLocation : {city : 'Chennai', state: 'Telangana' }}
);

上述使用 lodash 的答案有局限性,并未涵盖所有边缘情况。我刚刚想出了这个适用于所有场景的解决方案

import _ from 'lodash';
isSubset(obj1, obj2) {
  let matched = true;
  _.forEach(obj1, (value, key) => {
    if(!requirements || !_.isEqual(value, obj2[key])) {
      matched = false;
      return;
    }
  });
  return matched;
}

案例1:

const obj1 = { foo: 'bar' };
const obj2 = { foo: 'bar', baz: 'qux' };
console.log(isSubset(obj1, obj2)); // true

案例2:

const obj1 = { foo: 'bar' };
const obj2 = { foo: 'bar' };
console.log(isSubset(obj1, obj2)); // true

案例3:

const obj1 = { foo: 'bar', baz: 'qux' };
const obj2 = { foo: 'bar'};
console.log(isSubset(obj1, obj2)); // false

案例4:

const obj1 = undefiend;
const obj2 = undefiend;
console.log(isSubset(obj1, obj2)); // true

案例5:

const obj1 = undefiend;
const obj2 = { foo: 'bar'};
console.log(isSubset(obj1, obj2)); // true

案例6:

const obj1 = { foo: 'bar'};
const obj2 = undefiend;
console.log(isSubset(obj1, obj2)); // false
function isSubset(obj1, obj2) {
  for (var key in obj2){
     if (JSON.stringify(obj2[key]) === JSON.stringify(obj1[key]))
        return true;
  }
  return false;
}

编辑:现在是通用的,但如果想要它更通用,您应该看到以下链接进行比较https://stackoverflow.com/a/1144249/5965782

Nima 的第一个答案不可能是正确的,因为要使子集条件为真,"较小"集合中的所有 (不仅仅是某些)元素都需要包含在"较大"集合中。其余的基本上是正确的,只需将some替换为every,并交换两个对象(bigsmall):

/**
 * Determine whether "small" is a subset of "big"
 * @see https://stackoverflow.com/questions/35737312/find-if-an-object-is-subset-of-another-object-in-javascript/48971177#48971177
 */
function isSubset(big, small) {
  const { every, isEqual } = _;
  return every(small, 
    (v, k) => isEqual(v, big[k])
  );
}
// test it!
var object1 = { pickUpLocation : {city : 'Hyderabad', state: 'Telangana' }};
var object2 = { dist : 322, pickUpLocation:  {city : 'Hyderabad', state: 'Telangana' }};
var a = {i:1, j:2, k:3}; var b = {i:1, j:2}; var c = {i:2, j:2};
console.log([
  isSubset(a, b),
  isSubset(a, c),
  isSubset(b, a),
  isSubset(object1, object2),
  isSubset(object2, object1)
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

PS:这是另一种方法,但它可能会更慢,因为它会复制东西并且不会提前停止:

function isSubset(big, small) { 
  const { pick, isEqual } = _;
  return isEqual(pick(big, Object.keys(small)), small);
}

这是一个简单的解决方案:

  import _ from "lodash"
  // is a subset of b?
  function isSubset(a, b, merge = false) {
    const assign = merge ? _.merge : _.assign;
    var c = assign(_.cloneDeep(b), a);
    return _.isEqual(b, c);
  }

也有点晚了,但这是另一个不需要任何外部库的解决方案。 我基于@Akshay Kapoor 的答案,但这个答案处理日期和其他定义 valueOf() 的对象相等:

const isSubset = (superObj, subObj) =>
    superObj === subObj ||
    typeof superObj === "object" &&
    typeof subObj === "object" && (
        subObj.valueOf() === superObj.valueOf() /* dates & ? */ ||
        Object.keys(subObj).every(k => isSubset(superObj[k], subObj[k]))
    );
function isSubset(obj1, obj2) {
  const matches = [];
  for(const n1 in obj1) {
    let match = false;
    for(const n2 in obj2) {
      if(n1 == n2 && obj1[n1] == obj2[n2]) {
        match = true;
        break;
      }
    }
    matches.push(match);
  }
  return matches.every(Boolean);
}

英文:

object2中是否有一些关键满足其值与object1之间存在深度相等的条件?

写出来:

_.some(                       // Is there some key
  object2,                    // in object2
  function(val, key) {             // which satisfies the condition that
    return _.isEqual(         // there is deep equality between
      val,                    // its value and
      object1[key]                 // object1?
    );
  }
);

以较短的形式:

_.some(object2, function(val, key) { return _.isEqual(val, object1[key]); })

在 ES6 中:

_.some(object2, (val, key) => _.isEqual(val, object1[key]))

我的建议是通读 lodash 文档并学习所有 API,或者至少是主要的 API。例如,如果您不了解重要的例程,例如 _.some_.isEqual .另一方面,如果你确实了解他们,那么这是相当微不足道的。