【问题标题】:Find if an object is subset of another object in javascript在javascript中查找一个对象是否是另一个对象的子集
【发布时间】:2016-03-02 02:27:01
【问题描述】:

我需要一个函数 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

【问题讨论】:

  • 循环遍历object2的属性,检查值是否等于(_.isEqualobject1
  • 这个问题可能表明缺乏努力或研究,这是否决投票的绝佳理由。但是,由于寻求调试帮助但不包括最小示例等,它不满足 close 投票的标准,因为它首先没有寻求调试帮助。近距离投票者,请按照规定的标准谨慎投票。
  • 耸耸肩这是一个信息请求。帮我。 +1

标签: javascript lodash


【解决方案1】:

使用 Lodash isMatch

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

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

【讨论】:

  • 注意:null 被视为实际值。这意味着如果将{prop: 'object'} 替换为{prop: 'object', id: null},该函数将返回false
【解决方案2】:

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

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));

【讨论】:

    【解决方案3】:

    你可以尝试使用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' }}
    );
    

    【讨论】:

      【解决方案4】:

      使用 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)
      

      【讨论】:

      • 这是公认的答案试图做的,但他们误解了这个问题。 +1
      • @hraban 既然没有公认的答案了,请问您指的是哪个?
      • @Bondolin 不确定了,但从投票历史来看,它似乎是反对票之一。
      【解决方案5】:

      上述使用 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;
      }
      

      案例一:

      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
      

      【讨论】:

      • 您的 3 个示例包含拼写错误:undefiend -> undefined
      【解决方案6】:
      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

      【讨论】:

      • 函数应该是通用的
      • 哦,我的错,现在检查。
      • 不要使用字符串比较来检查对象是否相等。
      • 无论如何,他不想检查每个对象的属性值是否相同。他想检查一个对象中的属性值是否等于整个另一个对象。
      【解决方案7】:

      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);
      }
      

      【讨论】:

        【解决方案8】:

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

          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);
          }
        

        【讨论】:

          【解决方案9】:

          也有点晚了,但这是另一个不需要任何外部库的解决方案。我以@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]))
              );
          

          【讨论】:

            【解决方案10】:
            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);
            }
            

            【讨论】:

              【解决方案11】:

              英文:

              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 docs 并学习所有 API,或者至少学习主要的 API。例如,如果您不了解_.some_.isEqual 等重要例程,则此问题将很难自行解决。另一方面,如果您确实了解它们,那就很简单了。

              【讨论】:

              • 谢谢,这就是我要找的。​​span>
              • 不幸的是,我还没有足够的声誉,所以我无法投票赞成这个答案。
              • 这不符合原始海报所说的吗?我试过object1和object2,它返回false。
              • lodash every 是一个更好的解决方案。
              猜你喜欢
              • 2011-06-02
              • 1970-01-01
              • 2021-08-17
              • 2012-05-07
              • 2015-12-27
              • 1970-01-01
              • 2016-06-05
              • 2020-11-16
              • 1970-01-01
              相关资源
              最近更新 更多