Javascript 使用jQuery提高搜索JSON对象的性能
请原谅我,如果这个问题已经在某处得到了回答。我搜索过了,似乎这是一个相当具体的案例 下面是一个JSON示例(注意:这是一个非常精简的JSON,它是动态加载的,目前有126条记录): 我需要匹配正确的值组合。以下是我目前使用的函数:Javascript 使用jQuery提高搜索JSON对象的性能,javascript,jquery,json,Javascript,Jquery,Json,请原谅我,如果这个问题已经在某处得到了回答。我搜索过了,似乎这是一个相当具体的案例 下面是一个JSON示例(注意:这是一个非常精简的JSON,它是动态加载的,目前有126条记录): 我需要匹配正确的值组合。以下是我目前使用的函数: function drawOption(attid, optid) { var attlayout = layout[attid]; $.each(attlayout, function(k, v) { // d_opt_id and
function drawOption(attid, optid) {
var attlayout = layout[attid];
$.each(attlayout, function(k, v) {
// d_opt_id and d_opt_id are global scoped variable set elsewhere
if (v.design_attribute_id == d_att_id
&& v.design_option_id == d_opt_id
&& v.attribute_id == attid
&& ((v.apply_to_options == 1 || (v.option_id === optid)))) {
// Do stuff here
}
});
}
问题是我可能会迭代10-15个布局(唯一的attid),任何给定的布局(attid)可能有多达50种可能性,这意味着这个循环正在大量运行
考虑到必须匹配的多个条件,AJAX调用是否会更好?(这个JSON是通过PHP动态创建的,所以我可以设计一个PHP函数,可以更有效地实现这一点),
或者,我完全没有了解如何在JSON对象中查找项
一如既往,欢迎您提出任何改进代码的建议
编辑:我很抱歉没有说清楚,但这个问题的目的是想找到一种改进性能的方法。这个页面有很多javascript,我知道在这个位置上性能比实际情况要低。您考虑过使用jQuery grep函数吗
举个例子。这里有一种技术,它可能会以使用更多内存为代价,产生更好的性能 我将留下简单的代码示例来说明这个概念 首先,您需要将JSON数据预处理到一些作为索引的附加数组中。以下是预处理后最终阵列的外观示例:
var layouts_by_attribute = {
// attribute_id => array(layouts)
2: [40, 41, 44],
5: [326]
};
var layouts_by_design_attribute_id = {
// design_attribute_id => array(layouts)
4: [40, 41, 44, 326]
};
按属性查找布局现在非常快:
function findByAttribute(attribute_id) {
return layouts = layouts_by_attribute[attribute_id];
}
function findByDesignAttribute(design_attribute_id) {
return layouts = layouts_by_design_attribute[design_attribute_id];
}
我的第一个建议是停止使用
$。如果您想尽可能挤出每一点性能,请停止使用每一个。比传统的循环做得多一点。查看浏览器的调试器是否正在运行(即Safari/Chrome的web开发工具),并逐步完成调试,直到jQuery完全返回执行
供参考,小提琴的代码为:
var myArr = [{"foo":"bar"},{"answer":42}];
debugger;
$.each(myArr, function(k, v) {
console.log(k + ': ');
console.dir(v);
});
现在运行以下程序:
你会:
function foo(a, b) {
var gA = globalA,
gB = globalB;
if (a === gA && b === gB) {
// Do stuff
}
}
至于基于对象成员的条件配对,我看不出还有什么可以改进的。您正在检查的对象属性是顶级的,并且您正在查看每个对象的本地实例(因此范围链查找很短)
如果我不知道这到底是怎么回事,这些就是我能提出的最好的建议。然而,我可以猜测,您从更简单的JSON数据开始的想法将是一个巨大的改进。如果您知道布局及其约束是什么,那么从服务器请求特定的详细信息将意味着您不必检查这么多条件。您可以简单地向服务器询问实际需要实现和循环的详细信息(以更新DOM或其他内容)。首先,您应该测量,并且只有在存在真正的性能问题时才采取行动。你需要精确的数字,比如200毫秒或者80%的时间是在那里度过的。“它跑得很多”没有任何意义。浏览器可以快速循环
您可以像其他人提到的那样改进常量因子,比如使用本机for循环而不是jQuery.each。在这种情况下,更改全局变量不会对您有太大帮助
如果你真的想提高效率,你应该找到一个比O(n)更好的算法。假设您只使用这些数据来查找与特定条件匹配的元素,那么您可以使用JS对象作为散列来获得O(1)性能
仅举一个具体案例的示例:
var layout = {
"2": { "2,,4,131,10,0": ["40", "93"], "2,115,4,131,0": ["41"] },
"4": { ... },
...
};
在php中生成此输出相当容易,然后只需使用查找来查找与特定条件匹配的ID。在尝试改进代码时,最好使用firebug评测来检查哪些函数需要时间。您可以通过单击firebug控制台面板中的profile按钮进行配置,然后运行代码或在代码中使用
从您给出的代码中,只能给出几个改进点
$。与本机循环解决方案相比,每个解决方案都很慢。最好
循环解决方案,看看这个
最好将JSON更改为使用数组而不是对象文本。据说检索值的速度更快
我以前对这样的问题有过经验,我的js对象数组由8000条记录和更多记录组成。
我的经验不是关于性能,而是关于代码的可读性、可维护性和可伸缩性
因此,我在两年前开发了一个JS对象查询库:JSOQL
它的工作原理类似于SQL,允许您使用类似于SQL的语法查询js对象数组
示例用法是这样的,我记不清了,但是您可以在下载选项卡中下载示例用法
new JSQOL().Select([field1, field2, field3 ...]).From({ ... }) .Where(fn) .Offset(int) .Limit(int) .Get();
注:
{…}是您的对象数组,或者它本身就是一个对象
希望能有所帮助,如果您需要更多信息,可以给我发送消息。这不会在任何地方都起作用,但您的问题听起来是可以解决的
如果没有webworkers,我会考虑的另一件事是尽量不要长时间阻塞ui。如果你能将它分为大约40毫秒,然后在几毫秒后设置下一个chunck超时,用户将有一个更愉快的体验。这需要一点修改,但是当某个东西花费的时间超过50到100毫秒时,用户就会开始注意到它
5个字段:v.design\u attribute\u id、v.design\u option\u id、v.attribute\u id、v.apply\u to\u options、v.option\u id
您可以做的是向对象添加一个名为“key”的额外字段,该字段是这些字段中值的组合
这里有一个例子
{
"key": "4_131_2_0_0" //i picked 0 to represent null, but you can pick any number
"id": "40",
"attribute_id": "2",
"option_id": null,
"design_attribute_id": "4",
"design_option_id": "131",
"width": "10",
"height": "10",
"repeat": "0",
"top": "0",
"left": "0",
"bottom": "0",
"right": "0",
"use_right": "0",
"use_bottom": "0",
"apply_to_options": "0"
}
但请注意,必须规范化每个值的长度。
M
var layout = {
"2": { "2,,4,131,10,0": ["40", "93"], "2,115,4,131,0": ["41"] },
"4": { ... },
...
};
new JSQOL().Select([field1, field2, field3 ...]).From({ ... }) .Where(fn) .Offset(int) .Limit(int) .Get();
{
"key": "4_131_2_0_0" //i picked 0 to represent null, but you can pick any number
"id": "40",
"attribute_id": "2",
"option_id": null,
"design_attribute_id": "4",
"design_option_id": "131",
"width": "10",
"height": "10",
"repeat": "0",
"top": "0",
"left": "0",
"bottom": "0",
"right": "0",
"use_right": "0",
"use_bottom": "0",
"apply_to_options": "0"
}
function drawOption(attid, optid) {
var attlayout = layout[attid];
var needle = d_att_id + "_" + d_opt_id + "_" + attid + "_" + optid; //remember to normalize length if you have to
var idx = binarySearch(attlayout,needle);
var item;
if(idx !== -1){
item = attlayout[idx];
//do something
}
}
function drawOption(attid, optid) {
var needle = attid + "_" + d_att_id + "_" + d_opt_id + "_" + attid + "_" + optid; //remember to normalize length if you have to
var item = layout[needle];
if(typeof item !== "undefined"){
//do something
}
}
var layout = {
"2":[[...], ...],
"5":[[...], ...]
};
var index = {};
function makeKey(data) {
return data.join('_');
}
for(var l in layout) {
var cur = layout[l];
for(var i in cur) {
var item = cur[i];
var key = makeKey([item.p1, item.p2, ...]);
index[key] = index[key] || [];
index[key].push(item);
}
}
function find(attid, optid) {
var key = makeKey([attid, optid, 1, d_att_id, ...]);
return index[key]; //this is an array of results
}