比较两个对象,同时过滤掉特定键

时间:2018-09-17 22:23:00

标签: javascript object ecmascript-6

我正在尝试找出最佳方法。假设我有两个对象

const baseObject = {
   firstName: "John",
   lastName: "Doe",
   dob: "01/01/00",
   siblings: []
}

const updatedObject = {
   firstName: "Johnathan",
   lastName: "Doe",
   dob: "01/01/00",
   siblings: []
}

我想将baseObject与我的updatedObject进行比较,而忽略dob & siblings来查找任何差异和另一个obj中的更改。

我一直在努力做到这一点。我玩过.filter,.map等,但没有取得任何进展。

注意:是的[]实际上很重要。

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

  

我不希望不单独比较每个对象键值   因为最终,我希望我的物体会增长

如果您这么认为的话,查找javascript对象中的差异并不容易。没有任何魔术功能(我已经搜索了很多)可以为您完成此功能。这就是为什么您必须遍历键并手动进行所有操作的原因。

示例:

const changes = Object.keys(baseObject)
.filter(key => !['dob', 'siblings'].includes(key))
.map(key => (
  {
    property: key, 
    oldVal: baseObject[key], 
    newVal: updatedObject[key],
    wasUpdated: baseObject[key] === updatedObject[key]
  }
 ))

P.S。您没有提供结果应该是什么样子,所以我在不知道的情况下编写了代码。

答案 1 :(得分:1)

由于要比较有限键上的两个对象,因此您需要在条件中专门提及每个键,或者需要为这些键维护单独的内存。如果您的excluding键较少,则为including键保留一个数组。

const baseObject = {
  firstName: "John",
  lastName: "Doe",
  dob: "01/01/00",
  siblings: []
}

const updatedObject = {
  firstName: "Johnathan",
  lastName: "Doe",
  dob: "01/01/00",
  siblings: []
}

// Excluding
function compareWithoutKeys(first = {}, second = {}, excludes = []) {
  return Object.entries(first).every(([key, value]) =>
    excludes.includes(key) ? true : second[key] === value
  )
}
compareWithoutKeys(baseObject, updatedObject, ['dob', 'siblings']) // true/false

// Including
function compareWithKeys(first = {}, second = {}, includes = []) {
  return Object.entries(first).every(([key, value]) =>
    includes.includes(key) ? second[key] === value : true
  )
}
compareWithKeys(baseObject, updatedObject, ['firstName', 'lastName']) // true/false

更新后,不仅可以比较字符串。

如果要比较字符串而不是siblings(这是一个数组),则必须更新比较函数,您将检查值的类型,然后进行相应的比较。就像值是Object则比较每个键,或者值是Array然后比较每个索引。像这样:

function isEqual(first, second) {
  const firstType = Object.prototype.toString.call(first)
  const secondType = Object.prototype.toString.call(second)

  if (firstType !=== secondType) {
    return false
  }

  switch (expression) {
    case '[object Array]': return first.every((value, index) => value === second[index])
    case '[object Object]': return Object.entries(first).every((value, index) => value === second[index])
    default: return first === second
  }
}

// Excluding
function compareWithoutKeys(first = {}, second = {}, excludes = []) {
  return Object.entries(first).every(([key, value]) =>
    excludes.includes(key) ? true : isEqual(value, second[key])
  )
}
// usage
compareWithoutKeys(baseObject, updatedObject, ['dob', 'siblings']) // true/false
compareWithoutKeys(baseObject, updatedObject, ['dob']) // true/false

// Including
function compareWithKeys(first = {}, second = {}, includes = []) {
  return Object.entries(first).every(([key, value]) =>
    includes.includes(key) ? isEqual(value, second[key]) : true
  )
}
// usage
compareWithKeys(baseObject, updatedObject, ['firstName', 'lastName']) // true/false
compareWithKeys(baseObject, updatedObject, ['firstName', 'lastName', 'siblings']) // true/false

注意:这只会进行第一级比较,如果您想进行深层次比较(例如array of objects on which every key is an array),则必须使用递归函数或回退到 lodash 之类的库。

递归可能类似于以下内容,但我尚未测试以下代码。

function isEqual(first, second) {
  const firstType = Object.prototype.toString.call(first)
  const secondType = Object.prototype.toString.call(second)

  if (firstType !=== secondType) {
    return false
  }

  switch (expression) {
    case '[object Array]': return first.every((value, index) => isEqual(second[index], value))
    case '[object Object]': return Object.entries(first).every((value, index) => isEqual(second[index], value))
    default: return first === second
  }
}

关于递归同盟的文章: https://gomakethings.com/check-if-two-arrays-or-objects-are-equal-with-javascript/

Lodash的isEqual: https://lodash.com/docs/4.17.10#isEqual

答案 2 :(得分:1)

因为您有一个扁平的对象,并且不想在内部比较数组(顺序很重要),所以您可以stringify忽略它们,不需要它们的键并比较字符串。

const baseObject = {
    firstName: "John",
    lastName: "Doe",
    dob: "01/01/00",
    siblings: []
  },
  updatedObject1 = {
    firstName: "Johnathan",
    lastName: "Doe",
    dob: "01/01/00",
    siblings: []
  },
  updatedObject2 = {
    firstName: "John",
    lastName: "Doe",
    dob: "01/02/00",
    siblings: [10, 20]
  },
  keysToIgnore = ["dob", "siblings"],
  toJson = o => JSON.stringify(o, (k, v) => {
    if (!keysToIgnore.includes(k)) { return v }
  }),
  compare = (o1, o2) => toJson(o1)===toJson(o2);
  
  console.log('baseObject, updatedObject1: ' + compare(baseObject, updatedObject1));
  console.log('baseObject, updatedObject2: ' +compare(baseObject, updatedObject2));