首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用递归迭代器正确地迭代和分解结构。

无法使用递归迭代器正确地迭代和分解结构。
EN

Stack Overflow用户
提问于 2021-09-30 07:51:43
回答 1查看 75关注 0票数 0

我在使用RecursiveIterator时遇到了麻烦。

基本上,我需要对对象图进行迭代,以查看哪些属性mays已被修改以便能够在数据库中插入历史记录.

因此,我编写了以下类型记录代码,以便在VS代码中使用:

代码语言:javascript
复制
import RecursiveIterator = require("recursive-iterator");

const old = {
  vehicleId: 1,
  vehicleName: "Ol",
  modifiedProperties: [],
  device: {
    deviceId: 12,
    hardwareId: "12345",
    modifiedProperties: [],
  },
};

const n = {
  vehicleId: 1,
  vehicleName: "Ol2",
  modifiedProperties: ["vehicleName"],
  device: {
    deviceId: 12,
    hardwareId: "54321",
    modifiedProperties: ["hardwareId"],
  },
};

console.log("ouf");

var iteratorOnDeepClone = new RecursiveIterator(old, undefined, true);
var iteratorOnModifiedObject = new RecursiveIterator(n, undefined, true);

while (true) {
  let { value: valueOnModifiedObject, done: doneOnModifiedObject } =
    iteratorOnModifiedObject.next();
  let { value: valueOnDeepClone /*, done: doneOnDeepClone*/ } =
    iteratorOnDeepClone.next();

  if (valueOnDeepClone == undefined) {
    console.error("have a kitkat");
  }

  let {
    parent: parentOnDeepClone,
    node: nodeOnDeepClone,
    key: keyOnDeepClone,
    path: pathOnDeepClone,
    deep: deepOnDeepClone,
  } = valueOnDeepClone;
  let {
    parent: parentOnModifiedObject,
    node: nodeOnModifiedObject,
    key: keyOnModifiedObject,
    path: pathOnModifiedObject,
    deep: deepOnModifiedObject,
  } = valueOnModifiedObject;

  if (nodeOnModifiedObject.modifiedProperties != undefined) {
    for (var prop of nodeOnModifiedObject.modifiedProperties) {
      const oldValue: any = nodeOnDeepClone[prop];
      console.log(prop, oldValue);
    }
  }
  if (doneOnModifiedObject) {
    console.log("done!");
    break;
  }
}

现在它失败了(在第41行),因为iteratorOnDeepClone.next()返回的对象的某个点无效:

代码语言:javascript
复制
Exception has occurred: TypeError: Cannot destructure property 'parent' of 'valueOnDeepClone' as it is undefined.
  at Object.<anonymous> (d:\temp\sandbox\out\iterator_sample.js:33:19)
    at Module._compile (internal/modules/cjs/loader.js:1137:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47

package.json

代码语言:javascript
复制
{
  "name": "playground",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "recursive-iterator": "^3.3.0"
  },
  "devDependencies": {
    "ts-node": "^10.2.1",
    "tsconfig-paths": "^3.11.0",
    "typescript": "4.2.4"
  }
}

tsconfig.json

代码语言:javascript
复制
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "out",
    "sourceMap": true
  }
}

launch.json

代码语言:javascript
复制
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-node",
            "request": "launch",
            "name": "Launch Program",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "program": "${workspaceFolder}/iterator_sample.ts",
            "preLaunchTask": "tsc: build - tsconfig.json",
            "outFiles": [
                "${workspaceFolder}/out/**/*.js"
            ]
        }
    ]
}

编辑1:发现他停了下来,把火车停了下来。问题在于te modifiedProperties数组在不为空时被视为对象。所以迭代器被去同步。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-30 14:04:38

我认为这是一种发现差异的有问题的技术。

如果您试图并行地扫描它们,很可能您会发现差异只与添加属性的顺序有关,而不是与它们的值有关。想必这不是你想要的。

User Mulan有一个极好的回答,它解释了一种发现差异的好方法,为您提供了一个嵌套的结果对象,它非常详细地显示了事情发生变化的地方。这里有一种有点不同的技术,它使用'.'-separated键来平平对象来描述路径。

代码语言:javascript
复制
const compare = (a, b, first = transform (a), second = transform (b)) => 
  uniq (Object .keys (first) .concat (Object .keys (second)))
    .filter ((k) => first [k] !== second [k]) 
    .reduce ((a, k) => ((a [k] = {left: first [k], right: second [k]}), a), {})

const transform = (o) =>
  pathEntries (o) 
    .reduce ((a, [k, v]) => ((a[k .join ('.')] = v), a), {})

const pathEntries = (obj) =>
  Object (obj) === obj
    ? Object .entries (obj) .flatMap (
        ([k, x]) => pathEntries (x) .map (
          ([p, v]) => [[Array .isArray (obj) ? Number (k) : k, ... p], v]
        )
      ) 
    : [[[], obj]]

const uniq = (xs) => 
  [... new Set (xs)]

const orig = {
  foo: 42,
  bar: {baz: 99, qux: {corge: [1, 2, 3]}},
  grault: 'abc',
}

const modified = {
  foo: 42,
  bar: {baz: 99, qux: {corge: [1, 2, 4]}},
  waldo: 'xyz'
}

console .log (compare (orig, modified))
代码语言:javascript
复制
.as-console-wrapper {max-height: 100% !important; top: 0}

这是通过首先转动这样的对象来实现的:

代码语言:javascript
复制
const orig = {
  foo: 42,
  bar: {baz: 99, qux: {corge: [1, 2, 3]}},
  grault: 'abc',
}

转到

代码语言:javascript
复制
[
  [["foo"], 42],
  [["bar", "baz"], 99],
  [["bar", "qux", "corge", 0] ,1],
  [["bar", "qux", "corge", 1], 2],
  [["bar", "qux", "corge", 2], 3],
  [["grault"], "abc"]
]

使用实用程序pathEntries函数,然后在

代码语言:javascript
复制
{
  "foo": 42,
  "bar.baz": 99,
  "bar.qux.corge.0": 1,
  "bar.qux.corge.1": 2,
  "bar.qux.corge.2": 3,
  "grault": "abc"
}

transform内部。

我们对第一个和第二个对象执行此操作,然后简单地在输出对象中查找它们不同的键,并在单个对象结构中报告两个对象之间的不同值。

木兰的技术更加灵活,并且以一种更有条理的方式抓住了不同之处。不过,根据数据库的样式,该数据库的平面输出可能更适合存储在数据库中。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69388287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档