gpt4 book ai didi

javascript - 如何对对象进行版本控制?

转载 作者:太空狗 更新时间:2023-10-29 22:18:14 25 4
gpt4 key购买 nike

为了解释,请看下面正在更改的对象:

obj = {'a': 1, 'b': 2} // Version 1
obj['a'] = 2 // Version 2
obj['c'] = 3 // Version 3

我希望能够获得对象的任何这些版本,例如从版本 2 开始获取 obj。我不想每次更新单个键时都存储整个对象的副本。

我怎样才能实现这个功能?

我尝试使用的实际对象有大约 500,000 个键。这就是为什么我不想在每次更新时都存储它的完整副本。这个理论解决方案应该使用的编码语言是 pythonjavascript,但我会采用任何语言。

最佳答案

您可以为此使用 ES6 代理。这些将捕获对您的对象的任何读/写操作,并将每个更改记录在可用于来回滚动更改的更改日志中。

下面是一个基本实现,如果您打算在对象上应用除基本更新操作之外的其他功能,则可能需要更多功能。它允许获取当前版本号并将对象向后(或向前)移动到特定版本。每当您对对象进行更改时,它都会首先移动到其最新版本。

此片段显示了一些操作,例如更改字符串属性、添加到数组并移动它,同时向后和向前移动到其他版本。

编辑:它现在还可以将更改日志作为对象获取,并将该更改日志应用于初始对象。通过这种方式,您可以保存初始对象和更改日志的 JSON,并重播更改以获得最终对象。

function VersionControlled(obj, changeLog = []) {
var targets = [], version = 0, savedLength,
hash = new Map([[obj, []]]),
handler = {
get: function(target, property) {
var x = target[property];
if (Object(x) !== x) return x;
hash.set(x, hash.get(target).concat(property));
return new Proxy(x, handler);
},
set: update,
deleteProperty: update
};

function gotoVersion(newVersion) {
newVersion = Math.max(0, Math.min(changeLog.length, newVersion));
var chg, target, path, property,
val = newVersion > version ? 'newValue' : 'oldValue';
while (version !== newVersion) {
if (version > newVersion) version--;
chg = changeLog[version];
path = chg.path.slice();
property = path.pop();
target = targets[version] ||
(targets[version] = path.reduce ( (o, p) => o[p], obj ));
if (chg.hasOwnProperty(val)) {
target[property] = chg[val];
} else {
delete target[property];
}
if (version < newVersion) version++;
}
return true;
}

function gotoLastVersion() {
return gotoVersion(changeLog.length);
}

function update(target, property, value) {
gotoLastVersion(); // only last version can be modified
var change = {path: hash.get(target).concat([property])};
if (arguments.length > 2) change.newValue = value;
// Some care concerning the length property of arrays:
if (Array.isArray(target) && +property >= target.length) {
savedLength = target.length;
}
if (property in target) {
if (property === 'length' && savedLength !== undefined) {
change.oldValue = savedLength;
savedLength = undefined;
} else {
change.oldValue = target[property];
}
}
changeLog.push(change);
targets.push(target);
return gotoLastVersion();
}

this.data = new Proxy(obj, handler);
this.getVersion = _ => version;
this.gotoVersion = gotoVersion;
this.gotoLastVersion = gotoLastVersion;
this.getChangeLog = _ => changeLog;
// apply change log
gotoLastVersion();
}

// sample data
var obj = { list: [1, { p: 'hello' }, 3] };

// Get versioning object for it
var vc = new VersionControlled(obj);
obj = vc.data; // we don't need the original anymore, this one looks the same

// Demo of actions:
console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}. Change text:`);
obj.list[1].p = 'bye';
console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}. Bookmark & add property:`);
var bookmark = vc.getVersion();
obj.list[1].q = ['added'];
console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}. Push on list, then shift:`);
obj.list.push(4); // changes both length and index '4' property => 2 version increments
obj.list.shift(); // several changes and a deletion
console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}. Go to bookmark:`);
vc.gotoVersion(bookmark);

console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}. Go to last version:`);
vc.gotoLastVersion();
console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}. Get change log:`);
var changeLog = vc.getChangeLog();
for (var chg of changeLog) {
console.log(JSON.stringify(chg));
}

console.log('Restart from scratch, and apply the change log:');
obj = { list: [1, { p: 'hello' }, 3] };
vc = new VersionControlled(obj, changeLog);
obj = vc.data;
console.log(`v${vc.getVersion()} ${JSON.stringify(obj)}`);
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于javascript - 如何对对象进行版本控制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40497262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com