【问题标题】:Storing ordered object/array in localStorage在 localStorage 中存储有序对象/数组
【发布时间】:2012-04-02 05:43:40
【问题描述】:

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

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

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

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

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

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}]

第二种方法:我将命令存储在一个只包含一个属性的对象数组中,并简单地使用pushpopreverse维护年表。喜欢

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}
]

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

现在哪种方式效率更高。

提前致谢。

【问题讨论】:

    标签: javascript arrays sorting iteration local-storage


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您的数据架构需要一种同时提供唯一性和排序的数据类型。 其他语言会自动为您提供此功能(有序哈希等),但在 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}
      ]
      

      那么,让我们看看通过“命令”键对这个数组进行排序需要多长时间:

      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
      

      因此,除非您的对象包含超过 10 万个条目,否则排序时间将保持在 50 毫秒以下,这对于人类来说是难以察觉的。即使您的对象包含那么多条目,JSON. stringify 将成为您的瓶颈,而不是排序。

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

      【讨论】:

      • 那么迭代呢,迭代接管排序需要多长时间?
      • 在您提到的 1000-1500 范围内,您不会看到迭代和排序之间有任何明显的区别。在数百万范围内,迭代会快得多。问题是,通过选择“迭代”解决方案,您必须确保数组始终手动排序(通过弹出、推送等)您在代码中引入的任何错误都可能破坏您的数据。分拣解决方案更安全。
      • 如果我选择第一个选项,我将不得不创建一个像第二个这样的结构来进行排序,因为只有数组可以排序,对吗?至于由于错误而分解数据,只要它可以按正确的顺序显示最后 10 个命令,我就不太在意了。
      • 没错,您必须将对象放入数组中才能进行排序。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-12
      • 2011-03-06
      • 1970-01-01
      相关资源
      最近更新 更多