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

时间:2012-03-16 16:55:49

标签: javascript arrays sorting iteration local-storage

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

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

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

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

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

var command = $('textarea').val();
var storageTank = JSON.parse(localStorage["MyTank"]);
storageTank[command] = new Date().getTime();
localStorage["MyTank"] = JSON.stringify(storageTank);

所以我的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}]

第二种方法 :我将命令存储在只包含一个属性的对象数组中,只需使用pushpop和{{ 1}}为了保持年表。像

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);

现在,我不需要在每次要显示时对其进行排序,换句话说,每次页面加载时都需要对它们进行排序(由于表单提交在同一页面上重定向,因此非常频繁地发生)。但是如果在保存每个命令之前,我将需要首先遍历数组以检查天气是否已经存在相同的命令并覆盖它是否存在,并且这将在表单提交时发生,这意味着直到此事件已排序 out,表单不会提交。

现在哪种方式会更有效率。

提前致谢。

2 个答案:

答案 0 :(得分:3)

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

你提到你的storageTank对象包含很多对象,大约1000-1500,所以让我们看看对它进行排序需要多长时间:

为了进行测试,我创建了这个函数来生成一个类似于你的对象,它使用了underscore.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

我为许多build(size)值重复了这个测试,结果是:

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的条目,否则排序时间将保持在50毫秒以下,这对于人类来说是不明显的。即使您的对象包含那么多条目,也就是JSON。 stringify将成为你的瓶颈,而不是排序。

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

答案 1 :(得分:1)

你必须在javascript中存储有序列表或键值对之间进行选择,没有办法解决它。但是,V8引擎确实保留了键/值对的顺序。虽然需要通过广泛的测试来验证/确认。

相关问题