【问题标题】:How to check if values in one JavaScript object are present in another one?如何检查一个 JavaScript 对象中的值是否存在于另一个对象中?
【发布时间】:2016-06-05 03:03:26
【问题描述】:

我正在尝试比较 json_str1 和 json_str2,这里它应该返回 true,因为 json_str1 中的所有元素都存在于 json_str2 中。

现在我正在这样做

json_str1 = '{"0":"a","1":"b","2":"c"}';
json_str2 = '{"0":"c","1":"b","2":"a"}';

json_obj1 = $.parseJSON(json_str1);
json_obj2 = $.parseJSON(json_str2);

arr1 = $.map(json_obj1, function(el) { return el });
arr2 = $.map(json_obj2, function(el) { return el });

if($(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0)
    alert("equal");
else
    alert("not equal");

如何在不将对象转换为数组的情况下使其简短而简单?

https://jsfiddle.net/kq9gtdr0/

【问题讨论】:

  • 不应该是JSON.stringify(json_str1) === JSON.stringify(json_str2) Also see how to determine equality for two javascript objects
  • 如果只想检查 json_str1 中的所有字符是否存在于 json_str2 中,可以对 JSON.stringify(json_str1).sort() 进行简单排序,因为 json 对象可能不会在订购。
  • @Shubh,如果 json 与其他 json 对象的相同键值的顺序不同,它将失败。
  • 或许有必要问问他为什么要这样做,找到更简单的方法。
  • 既然没有人说过:javascript中没有JSON对象这样的东西。相反,有 JS 对象,可以使用 JavaScript Object Notation 显示为字符串.因此,既然您已经将 JSON 字符串解析为 JS 对象,那么您想要的是比较两个 JS 对象。

标签: javascript arrays json


【解决方案1】:

通过 @user663031 扩展了很棒的答案,如果您需要进行 deep 比较,下面是有效的代码:

export function objectOneInsideObjectTwo(jsonObj1: any, jsonObj2: any): boolean {
  return Object.keys(jsonObj1).every((k1) => {
    if (parseType(jsonObj1[k1]) === 'dict') {
      return objectOneInsideObjectTwo(jsonObj1[k1], jsonObj2[k1]);
    }
    if (parseType(jsonObj1[k1]) === 'array') {
      const results: boolean[] = [];
      jsonObj1[k1].forEach((o: any, i: number) => {
        if (parseType(o) === 'dict') {
          results.push(objectOneInsideObjectTwo(o, jsonObj2[k1][i]));
        } else {
          results.push(o === jsonObj2[k1][i]);
        }
      });
      return results.every((r) => r);
    }
    return Object.keys(jsonObj2).some((k2) => jsonObj1[k1] === jsonObj2[k2]);
  });
}

export function parseType<T>(v: T): string {
  if (v === null || v === undefined) {
    return 'null';
  }
  if (typeof v === 'object') {
    if (v instanceof Array) {
      return 'array';
    }
    if (v instanceof Date) {
      return 'date';
    }
    return 'dict';
  }
  return typeof v;
}

【讨论】:

    【解决方案2】:

    在您的问题和 cmets 中,您表示您只是希望验证“json_str1 中的所有元素都存在于 json_str2 中”。您的示例代码不只是这样做,它通过测试第一个对象中的所有键(不是值)是否在第二个对象中并且第二个对象中的所有键都在第一个对象中来检查键的完全相等性.通过查看您的代码,我假设当您说“元素”时,您的意思是键。

    除此之外,这可能会有所帮助:

    // Your first few lines of code
    
    json_str1 = '{"0":"a","1":"b","2":"c"}';
    json_str2 = '{"0":"c","1":"b","2":"a"}';
    
    json_obj1 = $.parseJSON(json_str1);
    json_obj2 = $.parseJSON(json_str2);
    
    // My new code
    
    var values1 = Object.keys(json_obj1).map(key => json_obj1[key]);
    var values2 = Object.keys(json_obj2).map(key => json_obj2[key]);
    
    // Check if every key in the first object is in the second object.
    values1.every(k1 => values2.indexOf(k1) >= 0);
    
    // OR
    
    // Check for equality of keys by checking both directions.
    values1.every(k1 => values2.indexOf(k1) >= 0) && values2.every(k2 => values1.indexOf(k2) >= 0);
    

    获取密钥需要 2 行,检查需要 1 行。您只需要这两项检查中的一项。

    【讨论】:

    • 但是来自 OP 解决方案 arr1 = $.map(json_obj1, function(el) { return el }); 的行返回了一个由 valuesNOT 键组成的数组。 $.mapvalue 作为第一个参数传递给回调。所以他的所作所为Object.keys 相同。您还误解了问题的一部分,即 它应该返回 true,因为 json_str1 中的所有元素都存在于 json_str2 中,它并不是说集合必须相同;它只是说第二组必须包含第一组。因此,双向检查是不必要和错误的。
    • @torazaburo 关于值而不是键的有效点。我不使用 jQuery 并且误解了 $.map 正在做什么。但是,我的问题的开头实际上解决了 contains 问题。他他想检查第二组是否包含第一组,但问题中的示例代码没有这样做,它检查相等性。 if($(arr1).not(arr2).length === 0 &amp;&amp; $(arr2).not(arr1).length === 0)我给出了两种解决方案的示例,因为问题与自身不一致。
    • 编辑答案以反映比较 values 而不是 keys
    • 经验教训,不要试图回答写得不好的问题。
    【解决方案3】:

    使用以下代码:

    Object.keys(json_obj1) . every(k1 => 
      Object.keys(json_obj2) . some(k2 =>
        json_obj1[k1] === json_obj2[k2]
      )
    );
    

    英文:

    Every key k1 in json_obj1 满足 some key k2 in json_obj2 满足json_obj1 的值与键k1 等于键json_obj2 的值k2

    或者用更会话的英语:

    第一个对象中的每个值都匹配第二个对象中的某个值。

    【讨论】:

    • 为什么 Object.keys(json_str1) 返回一个有 25 个属性的数组 ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"] ?而不是 json_str1 包含的 3 个属性;例如。; ["0", "1", "2"] ?
    • json_str1 是一个字符串。它不包含任何属性。这只是一个字符串。控制台将为字符串中的每个字符报告一个属性。您想检查 json_obj1 的属性,这是一个正确的 JavaScript 对象。
    • 您的解决方案将为json_str1 = '{"0":"aa","1":"b","2":"c"}'; json_str2 = '{"0":"c","1":"b","2":"a"}';返回true
    • 不,它返回 false。
    • 没有。我的 JS 说Object.keys(json_obj1)。你的小提琴说Object.keys(json_str1)。仔细注意json_str1json_obj1 之间的区别,json_obj1 是通过解析该字符串创建的 JavaScript 对象。请在jsfiddle.net/cLhs1bbc/1查看更正的小提琴。
    【解决方案4】:

    如果您想确定两个对象是否具有 相同 键,则无法做到这一点,除非至少将两个对象的键转换为带有 Object.keys 的数组或循环遍历两者对象!

    原因很简单:很明显,您必须比较两个对象的键数,唯一的方法是遍历所有属性或Object.keys

    所以我认为最短的方法是:

    json_obj1 = JSON.parse('{"0":"a","1":"b","2":"c"}');
    json_obj2 = JSON.parse('{"0":"c","1":"b","2":"a"}');
    
    keys_1 = Object.keys(json_obj1);
    keys_2 = Object.keys(json_obj2);
    
    if(keys_1.length === keys_2.length && keys_1.every(key => keys_2.indexOf(key) >= 0)) {
        alert('equal')
    } else {
        alert('not equal')
    }
    

    如果您只想检查 json1 中的所有键是否都存在于 json2 中,您可以这样做:

    json_obj1 = JSON.parse('{"0":"a","1":"b","2":"c"}');
    json_obj2 = JSON.parse('{"0":"c","1":"b","2":"a"}');
    if(Object.keys(json_obj1).every(key => key in json_obj2)) {
      alert('equal');
    } else {
      alert('not equal');
    }
    

    【讨论】:

    • 您的代码返回“不等于”,但正确答案是“等于”。
    • There is no way to do this without at least converting the keys of both Objects to an array with Object.keys or looping through both Objects! - Ermmmm,我想你会发现我做到了:D
    • @AdrianLynch 你觉得你的.filter 做了什么?
    【解决方案5】:

    如果你喜欢使用库,那么你可以使用下划线isMatch

    _.isMatch(object, properties)
    

    告诉你属性中的键和值是否包含在 对象。

    【讨论】:

      【解决方案6】:

      使用 lodash

      var _ = require('lodash');
      
      function compareValues(jstr1, jstr2) {
        return _.isEqual(_.valuesIn(JSON.parse(jstr1)).sort(), _.valuesIn(JSON.parse(jstr2)).sort());
      }
      
      json_str1 = '{"0":"a","1":"b","2":"c"}';
      json_str2 = '{"0":"c","1":"b","2":"a"}';
      
      console.log(compareValues(json_str1, json_str2));
      

      【讨论】:

      • 不要使用字符串比较来比较数组。
      • 你为什么这么说?
      • 例如,这种比较会错误地报告数组['1,', 2][1, ',2'] 相等。它还会报告数组[false]["false"] 相等。
      • 好点!猜我太专注于示例值都是字符串。
      【解决方案7】:

      有一种简单而准确的方法。

      您可以使用第三方但非常流行的实用程序库 Lodash。可以检查相等性的链接函数。

      1. 首先将两个 JSON 解析为对象
      2. 然后使用 _.values() 将每个键的所有键的值提取到单独的数组中
      3. 找出两个数组的差异。如果它是一个空数组,那么它们都是相等的。

      您可以将所有步骤链接到一个语句中,例如:

      _.isEmpty(_.difference(_.values(json_obj1), _.values(json_obj2)))
      

      示例:https://jsfiddle.net/kq9gtdr0/4/

      更多信息:

      https://lodash.com/docs#values

      https://lodash.com/docs#difference

      https://lodash.com/docs#isEmpty

      您可以包含来自 CDN(https://cdn.jsdelivr.net/lodash/4.5.1/lodash.min.js) 的库或下载并将其用作普通脚本。 Lodash 提供了大量有用的实用功能,使 JS 编程变得更加容易。你最好试试看。

      【讨论】:

      • 感谢您的回复。但我正在尝试如果'a','b'&'c'以任何顺序出现在两个json中,它应该是真的
      • @LearningMode 您的意思是如果 obj1 中的所有值都在 obj2 中,但是对于不同的键,您希望这两个对象相等吗?
      • 是的,我做到了,但时间很长。尽量缩短。
      • 我不会指定任何技术方式来做这件事,我在 JavaScript 方面不是那么好,但我想你应该知道 json 格式并没有指定键值对的顺序.所以 { 'a' : 1, 'b' : 2} 和​​ {'b' : 2, 'a' : 1} 实际上是同一个文档。此外,在许多语言中,它们由类似无序地图的结构表示,因此,一般而言,您不应指望它们的顺序。
      • @MarkBramnik 他只是在谈论价值观。它不像 { 'a' : 1, 'b' : 2} 和​​ {'b' : 2, 'a' : 1} 它像 1 和 2 存在于另一个对象中,即使对于不同的键,结果也应该是正确的像 { 'a' : 1, 'b' : 2} 和​​ {'a' : 2, 'b' : 1} 必须为真
      【解决方案8】:

      你可以试试这个

      var json_str1 = {"0":"a","1":"b","2":"c"};
      var json_str2 = {"0":"c","1":"b","2":"a"};
      var flag =  1;
      
      if(Object.keys(json_str1).length == Object.keys(json_str2).length){
          Object.keys(json_str1).forEach(function(x){
              if(!json_str2.hasOwnProperty(x) || json_str2[x] != json_str1[x]){
                  flag = 0;
                  return;
              }                      
          });
      }
      
      if(flag)
          alert('equal');
      else
          alert('Not Equal');
      

      【讨论】:

      • 它可能看起来很复杂,但它不需要任何第三方库
      • 它适用于任何顺序的每组值的每组键
      • 用户说他已经实现了但想缩短它。
      • @NidhinDavid : 请检查用户的回答和我的回答
      • @NidhinDavid:检查用户的实现是否给了对象相等但实际上它们不相等
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多