Javascript 在localStorage中存储有序对象/数组

Javascript 在localStorage中存储有序对象/数组,javascript,arrays,sorting,iteration,local-storage,Javascript,Arrays,Sorting,Iteration,Local Storage,我已经为我们的内部门户构建了这个chrome扩展。此门户中有一个表单,其中只有一个文本区域作为输入。用户通常以这种形式发布一组字符串。因此,我的扩展将这些值存储在本地提交上,并以相反的时间顺序显示用户在表单中发布的命令的历史记录 我目前所做的是将每个命令作为值存储,将当前时间戳作为键存储到localStorage中。如果用户两次发布相同的数据,则两个数据都存储为两个不同的键值对。在每次加载页面时,我从数组中的localStorage中检索所有键,并按逆时间顺序对数组进行排序。然后再次遍历该数组,

我已经为我们的内部门户构建了这个chrome扩展。此门户中有一个表单,其中只有一个文本区域作为输入。用户通常以这种形式发布一组字符串。因此,我的扩展将这些值存储在本地提交上,并以相反的时间顺序显示用户在表单中发布的命令的历史记录

我目前所做的是将每个命令作为值存储,将当前时间戳作为键存储到localStorage中。如果用户两次发布相同的数据,则两个数据都存储为两个不同的键值对。在每次加载页面时,我从数组中的localStorage中检索所有键,并按逆时间顺序对数组进行排序。然后再次遍历该数组,创建另一个包含键值对对象的数组。然后我在DOM节点中将它们显示为输入命令的历史记录

现在这是一种效率非常低的方法,更好的方法是将所有键值对存储在一个JSON.stringifyed字符串中。每当用户两次发布相同的输入时,就应该为相同的命令覆盖timestamp的前一个值。简而言之,同一命令不应存储两次

有两种方法可以做到这一点。那就是我需要帮助的地方

第一种方法:创建单个对象,键作为命令,值作为当前时间戳。说:

var command = $('textarea').val();
var storageTank = JSON.parse(localStorage["MyTank"]);
storageTank[command] = new Date().getTime();
localStorage["MyTank"] = JSON.stringify(storageTank);
所以我的储水箱看起来像

{ 
  "run": 1331916048253, 
  "stop": 1331916049963, 
  "modify":1331916086324,
  "delete": 1331916099874
  //and so on... Remember there can be as much as 1000 to 1500 of such commands,
  //some of them very large
}
现在,我的数据存储为无序字典。每当大部分是onload时,我需要以相反的时间顺序显示它们,我必须创建一个对象数组,每个对象包含一个键命令和查询时间戳,并对其进行排序。 像这样[{run:1331916048253},{stop:1331916049963},{modify:1331916086324},{delete:1331916099874}]

第二种方法:我将命令存储在一个只包含一个属性的对象数组中,并简单地使用push、pop和reverse来维护时间顺序。像

var command = $('textarea').val();
var entity = {};
entity[command] = new Date().getTime();
var storageTank = JSON.parse(localStorage["MyTank"]);
storageTank.push(entity);
localStorage["MyTank"] = JSON.stringify(storageTank);
现在我的储液罐看起来像这样

[
    {"run": 1331916048253},
    {"stop": 1331916049963},
    {"modify":1331916086324},
    {"delete": 1331916099874}
]
现在,我不需要在每次我想显示的时候对它们进行排序,或者换句话说,在每次页面加载时对它们进行排序,因为表单提交会在同一页面上重定向。但是,如果在保存每个命令之前,我需要首先遍历数组,检查同一命令是否已经存在,如果已经存在,则覆盖,这将发生在表单提交时,这意味着在解决此问题之前,表单不会提交

现在哪种方式更有效


提前感谢。

您的数据架构需要一种既能提供唯一性又能提供顺序的数据类型。 其他语言会自动为您提供排序哈希等,但在Javascript中,您需要在提供唯一性的对象或提供排序的数组之间进行选择

您提到您的storageTank对象包含许多对象,大约1000-1500个,所以让我们看看排序需要多长时间:

为了进行测试,我创建了这个函数,它生成了一个与您类似的对象,它使用下划线.js

function build (size) {
    return _.chain(size)
            .range()
            .shuffle()
            .map(function (v) {return {'command': v};})
            .value();
}

console.log(build(10));
> [
    {'command': 4},
    {'command': 0},
    {'command': 2},
    {'command': 8},
    {'command': 5},
    {'command': 1},
    {'command': 3},
    {'command': 9},
    {'command': 6},
    {'command': 7}
]
因此,让我们看看按“command”键对该数组排序需要多长时间:

b = build(10);
console.time('a');
b.sort(function (a, b) {return a.command - b.command});
console.timeEnd('a')

a: 0ms
我对许多buildsize值重复了此测试,结果如下:

size: 10,       time: 0ms
size: 20,       time: 0ms
size: 40,       time: 0ms
size: 80,       time: 0ms
size: 160,      time: 0ms
size: 160,      time: 0ms
size: 320,      time: 0ms
size: 640,      time: 0ms
size: 1280,     time: 1ms
size: 2560,     time: 1ms
size: 5120,     time: 3ms
size: 10240,    time: 5ms
size: 20480,    time: 10ms
size: 40960,    time: 28ms
size: 81920,    time: 43ms
size: 163840,   time: 228ms
size: 327680,   time: 444ms
size: 655360,   time: 997ms
size: 1310720,  time: 2330ms
因此,除非您的对象包含超过100K个条目,否则排序时间将保持在50ms以下,这对于人类来说是不可见的。即使您的对象包含那么多条目,JSON也会被删除。stringify将成为您的瓶颈,而不是排序


这意味着:排序非常快。使用第一种方法。

您的数据架构需要一种同时提供唯一性和顺序的数据类型。 其他语言会自动为您提供排序哈希等,但在Javascript中,您需要在提供唯一性的对象或提供排序的数组之间进行选择

您提到您的storageTank对象包含许多对象,大约1000-1500个,所以让我们看看排序需要多长时间:

为了进行测试,我创建了这个函数,它生成了一个与您类似的对象,它使用下划线.js

function build (size) {
    return _.chain(size)
            .range()
            .shuffle()
            .map(function (v) {return {'command': v};})
            .value();
}

console.log(build(10));
> [
    {'command': 4},
    {'command': 0},
    {'command': 2},
    {'command': 8},
    {'command': 5},
    {'command': 1},
    {'command': 3},
    {'command': 9},
    {'command': 6},
    {'command': 7}
]
因此,让我们看看按“command”键对该数组排序需要多长时间:

b = build(10);
console.time('a');
b.sort(function (a, b) {return a.command - b.command});
console.timeEnd('a')

a: 0ms
我对许多buildsize值重复了此测试,结果如下:

size: 10,       time: 0ms
size: 20,       time: 0ms
size: 40,       time: 0ms
size: 80,       time: 0ms
size: 160,      time: 0ms
size: 160,      time: 0ms
size: 320,      time: 0ms
size: 640,      time: 0ms
size: 1280,     time: 1ms
size: 2560,     time: 1ms
size: 5120,     time: 3ms
size: 10240,    time: 5ms
size: 20480,    time: 10ms
size: 40960,    time: 28ms
size: 81920,    time: 43ms
size: 163840,   time: 228ms
size: 327680,   time: 444ms
size: 655360,   time: 997ms
size: 1310720,  time: 2330ms
因此,除非您的对象包含超过100K个条目,否则排序时间将保持在50ms以下,这对于人类来说是不可见的。即使您的对象包含那么多条目,JSON也会被删除。stringify将成为您的瓶颈,而不是排序


这意味着:排序非常快。使用第一种方法。

您必须在javascript中存储有序列表或键值对之间进行选择,这是无法避免的。但是,V8引擎保留键/值对的顺序。尽管它需要通过大量测试进行验证/确认。

您必须在javascript中存储有序列表或键值对之间进行选择,但这是无法避免的。但是,V8引擎保留键/值对的顺序。尽管需要通过大量测试进行验证/确认。

迭代如何,需要多少时间
请问迭代是否接管排序?在您提到的1000-1500范围内,您不会看到迭代和排序之间有任何明显的区别。在数百万范围内,迭代将快得多。问题是,通过选择“迭代”解决方案,您必须确保数组总是按pop、push等手动排序。您在代码中引入的任何错误都可能破坏数据。排序解决方案更安全。如果我使用第一个选项,我将必须创建一个类似于第二个的结构来进行排序,因为只有数组可以排序,对吗?至于由于bug而分解数据,只要它能以正确的顺序显示最后10条命令,我就不太担心了。没错,你必须将对象推入数组中才能进行排序。那么迭代呢,迭代需要多少时间来完成排序?在您提到的1000-1500范围内,您不会看到迭代和排序之间有任何明显的区别。在数百万范围内,迭代将快得多。问题是,通过选择“迭代”解决方案,您必须确保数组总是按pop、push等手动排序。您在代码中引入的任何错误都可能破坏数据。排序解决方案更安全。如果我使用第一个选项,我将必须创建一个类似于第二个的结构来进行排序,因为只有数组可以排序,对吗?至于由于bug而分解数据,只要它能以正确的顺序显示最后10条命令,我就不太在意了。没错,为了进行排序,您必须将对象推入数组中。