繁体   English   中英

如何检查对象的键和深键是否相等,类似于lodash的isEqual?

[英]How to check if an object's keys and deep keys are equal, similar to lodash's isEqual?

因此,我处于一个独特的情况下,我有两个对象,并且我需要比较所述对象上的键,以确保它们与默认对象匹配。 这是我要执行的操作的一个示例:

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

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

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

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

这样,如果我向DefaultObject添加新选项,例如将'perm5'设置为'ADMIN',则它将更新用户的对象。 但是,如果它们的对象具有相同的键(它是最新的),则可以继续进行。

我需要进行比较,以防万一我在例如myobj1中添加新属性。 如果仅比较主级键(id,myobj1,myobj2),则不会知道是否将新键添加到myobj1或myobj2中。

抱歉,这是非常特殊的情况。 如果您能提供帮助,请先谢谢。

~~~~编辑~~~~

好吧,所以我实际上提出了一个功能,该功能完全可以满足我的需求。 问题是,我想缩小它,以免它不那么大。 此外,即使它为null,我似乎也找不到找到检查项目是否为对象的方法。 这个答案不是很有帮助。

这是我的工作职能。

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

是否可以使用它而不必放入空数组?

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

如果是这种情况,您可以尝试如下操作:

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时,将立即返回一些。 在这种情况下:如果另一个数组中未包含任何键( indexOf(key) < 0

好吧,所以我实际上提出了一个功能,该功能完全可以满足我的需求。 问题是,我想缩小它,以免它不那么大。 此外,即使它为null,我似乎也找不到找到检查项目是否为对象的方法。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM