我的应用正在检索json数据。 json文件有近千个单词,结构如下:
{"THEMES":{"THEME1":["ITEM1","ITEM2","ITEM3"],"THEME2":["ITEM1",...]...}}
该文件约为25kb。在我的应用程序的某个时刻,我需要比较哪个ITEM与哪个主题生成在角度ng-重复一个与单词相关的选定项目内。这是我的角度的一部分,它处理这些:
<div class="well">
<div class="input-group" bindonce ng-repeat="word_in_list in words_list">
<div class="form-group">
<select>
<option ng-selected="word_in_list.select == theme" ng-repeat="theme in themes" value="{{theme}}">{{theme}}</option>
</select>
</div>
<div class="form-group">
<input type="text" class="form-control" placeholder="{{word_in_list.input}}">
<span class="input-group-addon">
<input type="checkbox" ng-click="listControlWord($event, word_in_list.input, word_in_list.select)">
</span>
</div>
</div>
</div>
重要的一部分是:
$http.get('json/word_bank.json')
.success(function (result) {
$scope.themes = Object.keys(result.TEMAS);
for (var i = 0, z = $scope.themes.length; i < z; i++) {
for (var j = 0; j < result.TEMAS[$scope.themes[i]].length; j++) {
$scope.words_list.push({select: $scope.themes[i], input: result.TEMAS[$scope.themes[i]][j]});
}
}
});
问题是浏览器需要大约两分钟来呈现信息,并且它经常会崩溃浏览器。循环工作正常,信息正在检索好,它只是需要的时间是不可接受的。如何优化这些循环?
答案 0 :(得分:2)
你的算法是O(N ^ 2),除了特定领域的启发式方法之外,还没有办法解决这个问题。话虽这么说,你可以用不同的方式看待这一点。如果我正确理解问题,你真的想要连接数组。
以下是您要完成的performance test。
不幸的是,我认为你不能使用最有效的方法(利用apply
),但你可以使用这些技术的某种组合。通过连接所有数组,并保留关于连接数组中哪些索引与哪些&#34;键&#34;相关联的元数据,您可以将其减少为O(N)。
像...一样的东西。
<!doctype html>
<html lang="en">
<head>
<title>Test</title>
<script src="d3.js" charset="utf-8"></script>
</head>
<body>
<div id="divPerfTest"></div>
<script>
var result = {"THEMES":{"THEME1": ["ITEM1","ITEM2","ITEM3"],"THEME2":["ITEM1","ITEM2"]}};
var keys = Object.keys(result.THEMES),
master = [],
masterBreaks = [],
themeNames = [],
word_list = [],
theme, idx, key,
breakIdx = 0,
breakOffset = 0,
outStr = "";
for(idx = 0; idx < keys.length; idx++) {
key = keys[idx];
theme = result.THEMES[key];
master = master.concat(theme);
masterBreaks.push(theme.length);
themeNames.push(key);
}
masterBreaks.push(master.length); // need the last break to exceed last index
for (idx = 0; idx < master.length; idx++) {
if (idx >= masterBreaks[breakIdx] + breakOffset) {
breakOffset += masterBreaks[breakIdx++];
}
word_list.push({
select: themeNames[breakIdx],
input: master[idx]
});
}
for(idx=0; idx<word_list.length; idx++) {
outStr += "[ " + idx.toString() + " ] Select: " + word_list[idx].select + ", Input: " + word_list[idx].input + "<br/>";
}
document.querySelector("#divPerfTest").innerHTML = outStr;
</script>
</body>
</html>
但是,我认为更好的方法是更改数据架构。可以重构或按摩数据,使得主题的名称是对象的属性,而项目列表是同一对象的另一个属性,而不是使用定义不同主题的变量名称。然后你维护这些对象的列表......
{ THEMES: [
{ id: "THEME1",
data: ["ITEM1", "ITEM2"] },
{ id: "THEME2",
data: ["ITEM1", "ITEM2", "ITEM3"] }
}
答案 1 :(得分:0)
由于您只是循环遍历数组,您可以将其拆分为不同的部分,并使用计时器在迭代中处理每个部分而不是一次处理整个部分。
答案 2 :(得分:0)
好。我设法解决了将我的应用程序分页的问题。我从这里得到了代码: Code to tune long lists in AngularJs
希望这有助于其他人。最好的。