【问题标题】:iterating associative arrays taking too long迭代关联数组花费的时间太长
【发布时间】:2013-09-26 08:31:41
【问题描述】:

我有这个 javascript 对象,其中包含城市列表以及状态的依赖项详细信息。

var cityList = {
'1' : ['CITY_CODE_A','City A', '2','11','2'],
'2' : ['CITY_CODE_B','City B','','11',''],
'3' : ['CITY_CODE_C','City C', '','11','']
};
var stateList = {
'11' : ['STATE_CODE_A', 'State A'],
'12' : ['STATE_CODE_B', 'State B'],
'13' : ['STATE_CODE_C', 'State C'],
'14' : ['STATE_CODE_D', 'State D']
};

根据选择的状态,键被传递给一个函数,该函数将键与城市列表中的值(数组中的索引 3 元素)匹配,如果找到,则形成一个选项标签 <select>。 这是代码:

$.each(cityList, function(key, value) {
  if(selectedVal == value[3]){
  $("select[id='"+selectid+"']").append('<option value="'+value[0]+'" code="'+key+'">'    +value[1] + '</option>'); 
  }
});

现在,当这个城市列表增长到 5 万条记录 (2 MB) 时,一个州有 5 万个城市(性能测试),上面的代码需要 2 分钟才能在本地运行代码的 Windows 7 机器上加载城市列表下拉列表。尝试使用原生 for/in-loop 但没有得到满意的结果。

关于如何减少时间的任何想法?需要更改 JS 对象结构吗?

【问题讨论】:

  • 一次处理这么多记录会占用大量资源....如果您想支持这么多记录,您需要检查基于分页的解决方案
  • 您正在动态创建一个包含 50K 选项的下拉菜单?即使是瞬间发生,这样做又有什么意义?
  • @ArunPJohny - 基于分页的解决方案在这里不起作用,因为有一些东西需要对动作进行更改。这个列表可能不会那么长,但是处理这个对象/数组需要 2 分钟的时间。
  • 您的对象是在 DOM 中加载的还是通过 XHR 请求加载的?
  • @kanika 如果有超过 50,000 个选项,那么您做错了。这个数字需要缩小很多。作为用户,您是否会考虑使用具有超过 50,000 个选项的下拉菜单的网站?我会关闭浏览器并找到一个更好的网站。

标签: javascript jquery for-loop associative-array


【解决方案1】:

我也是更好地使用搜索而不是 50k 滚动项的朋友。但要回答您的问题,我会使用以下方法改进您的代码:

var html = '';
$.each(cityList, function (key, value) {
    html += '<option value="' + value[0] + '" code="' + key + '">' + value[1] + '</option>'
});

$("select[id='1']").append(html);

这将大大加快您的 option 创建速度,因为 DOM 只会更改一次,而不是像您在示例中所说的 50k 次。 (Short Demo)

【讨论】:

  • 感谢您的回答...是的,我尝试了 Pawel 提到的类似方法..它在很大程度上减少了时间..感谢您的建议 :)
【解决方案2】:

编辑:@downvoters,你能解释一下为什么你认为这是错误的吗?但首先尝试运行this test

如果您想获取特定州的城市,您可以创建一个以州 ID 为键的地图,

var cityList = {
   11 : [ ['CITY_CODE_A','City A', '2','11','2'], ['CITY_CODE_B','City B','','11',''] ],
   12 : [ ['CITY_CODE_C','City C', '2','12','2'], ['CITY_CODE_D','City D','','12',''] ]
}

现在你只需要遍历citylist[ selectedVal ]

$.each(cityList[selectedVal], function(key, value) {
  $("select[id='"+selectid+"']").append('<option value="'+value[0]+'" code="'+key+'">'    +value[1] + '</option>'); 
});

要进一步优化它,您应该避免在循环中进行 DOM 操作(添加 &lt;option&gt; 元素),而是将其缓冲:

var $selectEl = $('<select />');
$.each(cityList[selectedVal], function(key, value) {
  $selectEl.append('<option value="'+value[0]+'" code="'+key+'">'    +value[1] + '</option>'); 
});
$selectEl.attr( 'id', selectid );
$("select[id='"+selectid+"']").replaceWith( $selectEl );

【讨论】:

  • 如何更快地添加超过 50,000 个选项?
  • 我使 script 更快,因为:如果整个列表有 50K 选项,您需要平均迭代超过 1k 个元素(50K 城市/50 个州),它使 DOM 操作更加高效。
  • 你在这里做的绝对是不是避免循环操作DOM。
  • @Jon,对不起,错字。固定。
  • @pawel - 我试过了,没有改变 cityList 和函数..只是修改了 DOM 操作..这导致了更好的性能..现在大约需要 6 秒..好的指针..将尝试进一步减少时间..感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多