在JavaScript中比较数组时,如何“移动”数组/对象路径时执行检查和忽略?

时间:2020-11-01 18:10:20

标签: javascript arrays diff

我见过flitbit/diff,但它说:

简单地记录对数组的更改。我们最关心结构的形状;因此,我们没有时间确定对象是否从阵列中的一个插槽移至另一个插槽....

所以在那儿不行。

您将如何实施?似乎很难。是否可以建立这些现有库之一来忽略数组动作?还是您将如何从头开始直接实现它?

我的用例是,我想跟踪对JSON对象所做的所有更改,以便人们对所做的每次更改都能获得积分/报酬。但是,如果人们只是删除一个数组路径,然后又将其重新添加到用户界面的其他位置,那我就不愿意提出要点了,那很容易:)

我首先尝试考虑展平路径,然后在路径上使用正则表达式,但这似乎行不通:

const flat = require('flat')

const compute = (_a, _b) => {
  const a = flat(_a)
  const b = flat(_b)

  let r_a = []
  for (let k_a in a) {
    r_a.push([
      k_a,
      new RegExp(`^` + k_a.replace(/\./g, '\\.').replace(/\d+/g, '\\d+') + `$`)
    ])
  }

  let r_b = []
  for (let k_b in b) {
    r_b.push([
      k_b,
      new RegExp(`^` + k_b.replace(/\./g, '\\.').replace(/\d+/g, '\\d+') + `$`)
    ])
  }

  let diff = []
  for (let i = 0, n = r_a.length; i < n; i++) {
    let [k_a, r_a_i] = r_a[i]
    let matches = false
    k_b_loop:
    for (let k_b in b) {
      if (r_a_i.test(k_b) && a[k_a] === b[k_b]) {
        matches = true
        break k_b_loop
      }
    }
    if (!matches) {
      diff.push({
        type: 'remove',
        path: k_a
      })
    }
  }

  for (let i = 0, n = r_b.length; i < n; i++) {
    let [k_b, r_b_i] = r_b[i]
    let matches = false
    k_a_loop:
    for (let k_a in a) {
      if (r_b_i.test(k_a) && b[k_b] === a[k_a]) {
        matches = true
        break k_a_loop
      }
    }
    if (!matches) {
      diff.push({
        type: 'create',
        path: k_b
      })
    }
  }

  return diff
}

const test1 = () => {
  const a = { 
    a: [
      { a: 1, b: 2 },
      { a: 1, b: 3 }
    ],
    b: 1,
    c: 2
  }
  const b = { 
    a: [
      { a: 1, b: 3 },
      { a: 1, b: 1 },
      { a: 1, b: 4 }
    ],
    c: 3
  }
  const diff = computeDiff(a, b)
  console.log(diff)
}

test1()

0 个答案:

没有答案