我在使用RecursiveIterator时遇到了麻烦。
基本上,我需要对对象图进行迭代,以查看哪些属性mays已被修改以便能够在数据库中插入历史记录.
因此,我编写了以下类型记录代码,以便在VS代码中使用:
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()返回的对象的某个点无效:
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:47package.json
{
"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
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "out",
"sourceMap": true
}
}launch.json
{
// 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数组在不为空时被视为对象。所以迭代器被去同步。
发布于 2021-09-30 14:04:38
我认为这是一种发现差异的有问题的技术。
如果您试图并行地扫描它们,很可能您会发现差异只与添加属性的顺序有关,而不是与它们的值有关。想必这不是你想要的。
User Mulan有一个极好的回答,它解释了一种发现差异的好方法,为您提供了一个嵌套的结果对象,它非常详细地显示了事情发生变化的地方。这里有一种有点不同的技术,它使用'.'-separated键来平平对象来描述路径。
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)).as-console-wrapper {max-height: 100% !important; top: 0}
这是通过首先转动这样的对象来实现的:
const orig = {
foo: 42,
bar: {baz: 99, qux: {corge: [1, 2, 3]}},
grault: 'abc',
}转到
[
[["foo"], 42],
[["bar", "baz"], 99],
[["bar", "qux", "corge", 0] ,1],
[["bar", "qux", "corge", 1], 2],
[["bar", "qux", "corge", 2], 3],
[["grault"], "abc"]
]使用实用程序pathEntries函数,然后在
{
"foo": 42,
"bar.baz": 99,
"bar.qux.corge.0": 1,
"bar.qux.corge.1": 2,
"bar.qux.corge.2": 3,
"grault": "abc"
}在transform内部。
我们对第一个和第二个对象执行此操作,然后简单地在输出对象中查找它们不同的键,并在单个对象结构中报告两个对象之间的不同值。
木兰的技术更加灵活,并且以一种更有条理的方式抓住了不同之处。不过,根据数据库的样式,该数据库的平面输出可能更适合存储在数据库中。
https://stackoverflow.com/questions/69388287
复制相似问题