【问题标题】:How to check if an object's keys and deep keys are equal, similar to lodash's isEqual?如何检查一个对象的键和深键是否相等,类似于lodash的isEqual?
【发布时间】:2018-05-30 18:50:10
【问题描述】:

所以我处于一个独特的情况,我有两个对象,我需要比较所述对象上的键以确保它们与默认对象匹配。这是我正在尝试做的一个示例:

const _ = require('lodash');

class DefaultObject {
  constructor(id) {
    this.id = id;
    this.myobj1 = {
      setting1: true,
      setting2: false,
      setting3: 'mydynamicstring'
    };
    this.myobj2 = {
      perm1: 'ALL',
      perm2: 'LIMITED',
      perm3: 'LIMITED',
      perm4: 'ADMIN'
    };
  }
}

async verifyDataIntegrity(id, data) {
  const defaultData = _.merge(new DefaultObject(id));
  if (defaultData.hasOwnProperty('myoldsetting')) delete defaultData.myoldsetting;
  if (!_.isEqual(data, defaultData)) {
    await myMongoDBCollection.replaceOne({ id }, defaultData);
    return defaultData;
  } else {
    return data;
  }
}

async requestData(id) {
  const data = await myMongoDBCollection.findOne({ id });
  if (!data) data = await this.makeNewData(id);
  else data = await this.verifyDataIntegrity(id, data);
  return data;
}

让我解释一下。首先,我有一个默认对象,每次用户首次使用该服务时都会创建该对象。然后,将该对象修改为其自定义设置。例如,他们可以将 'setting1' 更改为 false,同时将 'perm2' 更改为 'ALL'。

现在,我的默认对象的旧版本曾经有一个名为“myoldsetting”的属性。我不希望较新的产品具有此设置,因此每次用户请求他们的数据时,我都会检查他们的对象是否具有设置“myoldsetting”,如果有,请将其删除。然后,为了防止不必要的更新(因为这被称为每次用户想要他们的数据),我检查它是否与新的默认对象相等。

但这不起作用,因为如果用户更改了设置,它将始终返回 false 并强制更新数据库,即使没有任何键发生更改。为了解决这个问题,我需要一种方法来比较对象上的 ,而不是任何键和数据。

这样,如果我向 DefaultObject 添加一个新选项,比如将“perm5”设置为“ADMIN”,那么它将更新用户的对象。但是,如果他们的对象具有相同的键(它是最新的),那么继续你的一天。

我需要进行深入比较,以防我在 myobj1 中添加新属性。如果我只比较主级别的键(id、myobj1、myobj2),它不会知道我是否在 myobj1 或 myobj2 中添加了新键。

如果这没有意义,我深表歉意,这是一个非常具体的情况。如果您能提供帮助,请提前致谢。

~~~~编辑~~~~

好的,所以我实际上想出了一个完全符合我需要的函数。问题是,我想缩小它,使它不那么大。此外,我似乎无法找到一种方法来检查一个项目是否是一个对象,即使它是空的。这个答案不是很有帮助。

这是我的工作函数。

function getKeysDeep(arr, obj) {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'object') {
      arr = getKeysDeep(arr, obj[key]);
    }
  });
  arr = arr.concat(Object.keys(obj));
  return arr;
}

用法

getKeysDeep([], myobj);

是否可以不用放空数组也能使用?

【问题讨论】:

    标签: javascript node.js underscore.js lodash


    【解决方案1】:

    那么,如果我理解正确,您想比较两个对象的键,对吗?

    如果是这种情况,您可以尝试以下方法:

    function hasSameKeys(a, b) {
      const aKeys = Object.keys(a);
      const bKeys = Object.keys(b);
      return aKeys.length === bKeys.length && !(aKeys.some(key => bKeys.indexOf(key) < 0));
    }
    

    Object.keys(x) 将为您提供对象自身属性的所有键。

    如果值不在调用 indexOf 的数组中,则 indexOf 将返回 -1。

    只要数组的任何元素 (aKeys) 在回调中计算为 true,some 就会返回。在这种情况下:如果任何键不包含在另一个数组中(indexOf(key) &lt; 0

    【讨论】:

    • 不做深度检查
    • 这是正确的 - 从示例代码来看,对象没有嵌套属性。但是,您当然是对的,如果需要对键进行深度相等,则上述解决方案是不够的
    • 明确声明... “我需要这个比较深入”
    • 欣赏答案和解释,不过! :)
    【解决方案2】:

    好的,所以我实际上想出了一个完全符合我需要的函数。问题是,我想缩小它,使它不那么大。此外,我似乎无法找到一种方法来检查一个项目是否是一个对象,即使它是空的。

    最后,这对我有用。如果有人可以改进它,那就太棒了。

    function getKeysDeep(obj, arr = []) {
      Object.keys(obj).forEach(key => {
        if (typeof obj[key] === 'object' && !Array.isArray(obj[key]) && obj[key] !== null) {
          arr = this.getKeysDeep(obj[key], arr);
        }
      });
      return arr.concat(Object.keys(obj));
    }
    getKeysDeep(myobj);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      • 1970-01-01
      • 2015-06-03
      • 2021-04-27
      • 2015-07-27
      • 1970-01-01
      • 2021-01-17
      相关资源
      最近更新 更多