我正在使用Javascript并创建一个脱机应用程序。
我有一个很大的阵列,超过10mb。我需要从用户进行更改的阵列中保存元素,但是将阵列写入/读取到磁盘的速度太慢。
我想创建一个第二个数组,该数组仅保存用户所做的更改,因此我可以保存该较小的数组,然后在需要加载更改时可以将其更改镜像到较大的数组。
例如:
lib[x][1][y][6] = "no";
libVars[x][1][y][6] = "no";
libVars只会将元素更改保存在lib中,并且与大型数组lib的大小不同,因为用户只能与大型数组的一小部分进行交互。
显然这是行不通的,因为libVars与lib的结构不同,如果这样做,它还将占用大量内存(我还是这么认为!)
然后,我想遍历libVars并在已将更改保存在libVars中的相同元素点处更新lib。
有没有一种方法可以保存指向lib中某个位置的指针,该指针可以与相关的元素值一起存储在libVars中?
任何帮助将不胜感激。
谢谢。
=====================
我的大型阵列样品
var lib = [
[241,[[221119,"sample data","sample","no","no",131,"no"],
[221121,"sample2 data","sample2","no","no",146,"no"],
[221123,"sample3 data","sample3","no","no",28,"no"],
[221626,"sample4 data","sample4","no","no",26,"no"],
[221628,"sample5 data","sample5","no","no",88,"no"]]],
[330,[[305410,"2sample data","sample 2b","no","no",197,"no"],
[305412,"2sample 2 data","sample2 2b","no","no",147,"no"],
[305414,"3sample 2 data","sample3 2b","no","no",10,"no"] ...
尝试使用Z-Bone发布的解决方案
我已经添加了tempLib var,但是我看不到您最终如何更新实际的lib对象
Object.entries(libVars).forEach(([path, value]) => {
var tempLib = lib;
var pathParts = path.split('#');
pathParts.forEach((pathPart, index) => {
if (index == pathParts.length-1) {
tempLib[pathPart] = value;
} else {
//I don't fully track what you are doing here.
//I assume you are building the array path, but to me it looks like
// it's getting wiped out and not built upon?
tempLib = tempLib [pathPart];
}
});
});
答案 0 :(得分:2)
更新28/01/2019 根据nomaam的测试数据
@nomaam请检查以下代码段。我让它更改了lib
数组中的任意路径。我选择的路径是:lib[0][1][3][4]
。
您可以看到它最初如何返回值"no"
,然后在执行修改跟踪解决方案之后如何返回值"yes"
。
// First Step: Original Data (lib)
var lib = [
[241,[[221119,"sample data","sample","no","no",131,"no"],
[221121,"sample2 data","sample2","no","no",146,"no"],
[221123,"sample3 data","sample3","no","no",28,"no"],
[221626,"sample4 data","sample4","no","no",26,"no"],
[221628,"sample5 data","sample5","no","no",88,"no"]]],
[330,[[305410,"2sample data","sample 2b","no","no",197,"no"],
[305412,"2sample 2 data","sample2 2b","no","no",147,"no"],
[305414,"3sample 2 data","sample3 2b","no","no",10,"no"]]]]
// Log initial value in arbitrary selection lib[0][1][3][4]
console.log(lib[0][1][3][4])
// Second Step: Pointer's object
var libVars = {}
// Example of changing a value via an artificial "pointer" to lib[0][1][3][4]
libVars['0#1#3#4'] = 'yes'; // original value is "no"
// Third Step: Run the modifier - update changes from libVars to lib
Object.entries(libVars).forEach(([path, value]) => {
var tempLib = lib;
var pathParts = path.split('#');
pathParts.forEach((pathPart, index) => {
if (index == pathParts.length - 1) {
tempLib[pathPart] = value;
} else {
tempLib = tempLib[pathPart];
}
});
});
// Log the change fro lib
console.log(lib[0][1][3][4])
原始答案
如果我正确理解了您的挑战,从技术上讲,您可以持有一个对象,该对象具有要修改的属性的路径作为键,而修改后的值作为其值。
假设你的原始对象看起来像这样:
var lib = {a: {b: { c: { d: "yes"}}}}
您可以在备份对象中保留更改记录(例如,值从“是”更改为“否”)。
它可能看起来像这样,使用.
标记的嵌套属性。
var libVars = {};
libVars['a.b.c.d'] = "no";
然后,当您想更新原始的大型数组/值对象时,可以执行以下操作:
Object.entries(libVars).forEach(([path, value]) => {
var tempLib = lib;
// split by nesting indicator -> dot
var pathParts = path.split('.');
// iterate all parts of the path to the modified value
pathParts.forEach((pathPart, index) => {
if (index == pathParts.length-1) {
// once you made your way to last index, update value
tempLib[pathPart] = value;
} else {
tempLib = tempLib[pathPart];
}
})
})
console.log(lib); // outputs => {a: {b:{c: {d : "no"}}}}
答案 1 :(得分:1)
更新2
更新了我的答案,以摆脱lodash
,它似乎等于Z-Bone
的答案。他的变体比我的更清楚。
更新于@ 28.01.2019
var lib = [
[241,[[221119,"sample data","sample","no","no",131,"no"],
[221121,"sample2 data","sample2","no","no",146,"no"],
[221123,"sample3 data","sample3","no","no",28,"no"],
[221626,"sample4 data","sample4","no","no",26,"no"],
[221628,"sample5 data","sample5","no","no",88,"no"]]],
[330,[[305410,"2sample data","sample 2b","no","no",197,"no"],
[305412,"2sample 2 data","sample2 2b","no","no",147,"no"],
[305414,"3sample 2 data","sample3 2b","no","no",10,"no"]]]];
// object to track edits
var edits = {
'0.1.2.2': 'edited'
};
// sample/simple implementation of lodash's 'set' function
function applyEdit(arr, path, value) {
var items = path.split('.');
var last = items.length - 1;
var current = arr;
items.forEach(function (item, i) {
if (i !== last) {
current = current[item];
}
});
current[items[last]] = value;
}
// our restoration function
function patch(arr, edits) {
Object.keys(edits).forEach(function(key) {
var newValue = edits[key];
applyEdit(arr, key, newValue);
});
}
console.log(lib[0][1][2][2]) // "sample3"
// now we can restore our edits
patch(lib, edits);
console.log(lib[0][1][2][2]) // "edited"
// --------------------------------------------------------
// to prevent forgetting to track the updates you can use utility function
// to make changes to your 'lib' array
function update(arr, path, value) {
applyEdit(arr, path, value);
edits[path] = value;
}
原始答案:
一种可能的解决方案是让一个对象跟踪所有更改。
const edits = {};
,当您使用lib[x][1][y][6] = "no";
更新对象时,您还保存了修改:
edits[`${x}.1.${y}.6`] = "no";
基本上,您只是创建一个包含更改路径的字符串。
从文件加载您的edits对象后,您可以使用以下代码将所有更改应用于原始数组:
import { set } from 'lodash';
function patch(arr, edits) {
Object.keys(edits).forEach(key => {
const newValue = edits[key];
set(arr, key, newValue);
});
}
答案 2 :(得分:0)
假设libVars
中的路径与lib
中的路径相同,那么您只需将更改记录到一系列函数中,然后在lib
对象上重新应用这些函数:>
const data = {foo: 'aaa', bar: 'bbb'};
console.log('data before:', data);
const updates = [];
updates.push(obj => {
obj.foo = 'foo';
});
updates.push(obj => {
obj.bar = 'bar';
});
updates.forEach(fn => fn(data));
console.log('data after:', data);
答案 3 :(得分:0)
这可以使用代理通过模拟自动生存来处理。参见: