音乐:2个数组循环赋值的 效率问题
2012-01-13 15:54:24 作者:sandy 来源: 浏览次数:0
本帖最后由 mingxuan3000 于 2011-10-20 17:48 编辑
问题1
var useObj ={};
useObj .key1 = "a"
useObj .key2 = "b"
useObj .key3 = "x"
useObj .value1="kk"
useObj .value2="jj"
useObj .value3="cc"
useObj .value4="dd"
useObj .value5="dd"
useObj .value6="dd"
useObj .value7="dd"
var array1=[] //array1中有700个 useObj
var array2=[] //array2中有12000个 useObj
上面array1是array2的子集,不过里面的value值都更新过
要把array1中3个key值同时等于array2 的值付给array2,有什么好的方法?
for(var i = 0; i < array1.length; i++) {
for(var j= 0; j< array2.length; j++) {
if (array1[i].key1 == array2[j].key1&& array1[i].key2== array2[j].key2 && array1[i].key3 == array2[j].key3) {
array2[j] = array1[i]
break;
}
}
}
用上面一般的2重循环赋值,页面上会产生下面的提示
以上代码只是语法描述。
IE提示对话框 “是否停止运行此脚本?此页面上的脚本造成Internet Explore运行速度减慢。如果继续运行,您的计算机将可能停止响应。”
怎么能提高效率,避免产生上面的对话框?也可以使用jquery来解决
当然是越快越好,避免弹出这个对话框。
顺便问下 一般上面IE提示对话框产生的原因是 js代码执行时间过长,还是js代码执行太占内存,或者js代码执行的行数超过一定的限制才产生上面的对话框?
|||上面写的不清楚,我觉得你先把ARRAY1 和 ARRAY2 按什么东西排序下再比较吧。这个可能会好点。|||有什么不清楚的?
就是要把ARRAY1 全部更新到 ARRAY2 中去,按一般的方法,会产生上面那个IE提示对话框。
现在关键是不要产生这个对话框。提高循环效率可能是一个方法。。。|||for(var i = 0; i < array1.length; i++) {
for(var j= 0; j< array2.length; j++) {
if (array1这里是不是少了个[i].key1 == array2[j].key1&& array1还有这.key2== array2[j].key2 && array1.key3 == array2[j].key3) {
array2[j] = array1[i]
break;
}
}
}
我倒觉得不是效率的问题 是你访问到一些无法访问的对象或属性 导致出现的这个吧||| 本帖最后由 mingxuan3000 于 2011-10-20 17:46 编辑
上面代码只是描述算法的,实际代码中不存在语法错误什么的。小数据量时是可以正常运行的,到上面提的的数据量时,就会产生那个对话框。
这个编辑器那个重新编辑不行。。。
|||死循环了....for(var i = 0; i < array1.length; i++) { 你的array再改变 长度也在改变 你试一下用for(var i = 0,j= array1.length;i<j; i++)这样的办法
|||因为是用key合成索引,所以可以试一下用哈希的方式 ,
如果数据量实现太多, 也可以尝试添加定时器来异步执行
先谢谢大家的参与。
主要是解决 浏览器的问题,就是不要弹出那个 IE提示对话框。看来我要试试定时器了。当然我的代码里面还有很多别的处理,别的处理我也会再看看有没有问题。
现在我把 var useObj ={};加了一个 index属性
useObj.index=1//从1按顺序增加
array2中的数据完全按index排列,
这时循环array1,可以利用useObj.index属性直接定位到array2的index里面进行更新。
array1的数据如果是700可以不弹出对话框,如>700还是会弹出,我先看看定时器的方法。
大家谈谈弹出ie对话框的触发机理是什么?在什么情况下弹出这个对话框?有没有官方的解释说明。
|||看来我的标题有点不是很确切呀。现在2重循环我换成一重循环,还是不能完全解决。
当时也是页面上的元素太多了,大概好几千个link吧|||产生这种问题的主要原因是运行JS的语句太多,JS解释器长时间得不到释放,所以才弹出这种提示!
其实ff或者其他浏览器也会,只是ie一次能执行的代码句数少一些就会弹这个!
建议的解决方案两步实行:
1.改变数据结构,看你上面的var useObj ={};这个数据结构真的是烂的可以!
2.分段执行,采用定时器实现代码分段,使JS引擎有休息的时间!
针对数据结构
var useObj ={};
useObj .key1 = "a"
useObj .key2 = "b"
useObj .key3 = "x"
useObj .value1="kk"
useObj .value2="jj"
useObj .value3="cc"
useObj .value4="dd"
useObj .value5="dd"
useObj .value6="dd"
useObj .value7="dd"
这个Key假如合并掉
useObj={
key:'a,b,x',//3key合一,也没丢失你上面的信息
value:[
'kk',
'jj',
'cc',
.....
]
}
这么数据结构,key上的判断,if (array1[i].key1 == array2[j].key1&& array1[i].key2== array2[j].key2 && array1[i].key3 == array2[j].key3) {
这里就减少了2倍运算。
至于分段,楼上也有人写到!
最后,我有点 不明的是你为何这样copy来copy去的呢!
arr1和arr2中的数据都是引用类型的Object
你完全可以使用引用类型的特征来实现数据更新啊!
举个例子
var useobj={
value:1
};
arr1=[
useobj
];
arr2=[
useobj
]
这个时候,你改变arr1[0].value=2
那么arr2[0].value===2
最终我的解决方案就是
1.减少JS语句和分段JS语句
2.根据实际情况来改变功能的实现方式
||| 本帖最后由 mingxuan3000 于 2011-10-24 15:44 编辑
to:zjfeihu
不是copy来copy去,array2是页面上的总的数量,array1是页面经过后台处理(ajax),更新返回的一部分数据,他返回页面后,要更新array2
现在我来试试用setTimeOut来分段执行。
改变功能的想法也想过,但是项目马上上线了,如果改设计的话来不及了,只能先对付对付,当然这种大数据是最极端的情况(页面是根据设定动态显示的),一般的数据量是不会出这个问题的
但是据说好像上线前要进行一个评估,看能不能上线,估计极端数据量测试也是一个方面|||用setTimeOut来分段执行也不行。。。。看来瓶颈没有找对。。。|||var index = {};
function insert(key1,key2,key3,obj) {
if(!index[key1])index[key1] = {};
if(!index[key1][key2])index[key1][key2] = {};
if(!index[key1][key2][key3])index[key1][key2][key3] = obj;
}
for(var i = 0; i < array2.length; i++)
{
insert(array2[i].key1,array2[i].key2,array2[i].key3,array2[i]);
}
for(var i = 0; i < array1.length; i++)
{
var obj = index[arr1[i].key1][arr1[i].key2][arr1[i].key3];
obj.value1 = arr1[i].value1;
//...
}
|||最后问题没有解决,等解决了在来结贴
。。。|||var arr1=[],arr2=[],i=0;
function CreateObj()
{
this.key1 = "a";
this.key2 = "b";
this.key3 = "x";
this.value1 = "kk";
this.value2 = "jj";
this.value3 = "cc";
this.value4 = "dd";
this.value5 = "dd";
this.value6 = "dd";
this.value7 = "dd";
}
for(i=0;i<10000;i++)
{
arr1[i]=new CreateObj();
}
for( i=0;i<1000000;i++)
{
arr2[i]=new CreateObj();
}
for (i = 0; i < arr1.length; i++) {
for (var j = 0; j < arr2.length; j++) {
if (arr1[i].key1 == arr2[j].key1 && arr1[i].key2 == arr2[j].key2 && arr1[i].key3 == arr2[j].key3) {
arr2[j] = arr1[i];
break;
}
}
}没提示 我擦|||采自<高性能网站建设进阶指南>P102
Internet Explorer监控脚本执行的语句的数量达到最大限定值,默认为500万,就会弹出中止脚本运行的对话框
firefox检测脚本运行的总时间,当超过预定设定的时间,默认为10秒,就会弹出中止脚本运行的对话框
..|||
最好这样写:
问题1
var useObj ={};
useObj .key1 = "a"
useObj .key2 = "b"
useObj .key3 = "x"
useObj .value1="kk"
useObj .value2="jj"
useObj .value3="cc"
useObj .value4="dd"
useObj .value5="dd"
useObj .value6="dd"
useObj .value7="dd"
var array1=[] //array1中有700个 useObj
var array2=[] //array2中有12000个 useObj
上面array1是array2的子集,不过里面的value值都更新过
要把array1中3个key值同时等于array2 的值付给array2,有什么好的方法?
for(var i = 0; i < array1.length; i++) {
for(var j= 0; j< array2.length; j++) {
if (array1[i].key1 == array2[j].key1&& array1[i].key2== array2[j].key2 && array1[i].key3 == array2[j].key3) {
array2[j] = array1[i]
break;
}
}
}
用上面一般的2重循环赋值,页面上会产生下面的提示
以上代码只是语法描述。
IE提示对话框 “是否停止运行此脚本?此页面上的脚本造成Internet Explore运行速度减慢。如果继续运行,您的计算机将可能停止响应。”
怎么能提高效率,避免产生上面的对话框?也可以使用jquery来解决
当然是越快越好,避免弹出这个对话框。
顺便问下 一般上面IE提示对话框产生的原因是 js代码执行时间过长,还是js代码执行太占内存,或者js代码执行的行数超过一定的限制才产生上面的对话框?
|||上面写的不清楚,我觉得你先把ARRAY1 和 ARRAY2 按什么东西排序下再比较吧。这个可能会好点。|||有什么不清楚的?
就是要把ARRAY1 全部更新到 ARRAY2 中去,按一般的方法,会产生上面那个IE提示对话框。
现在关键是不要产生这个对话框。提高循环效率可能是一个方法。。。|||for(var i = 0; i < array1.length; i++) {
for(var j= 0; j< array2.length; j++) {
if (array1这里是不是少了个[i].key1 == array2[j].key1&& array1还有这.key2== array2[j].key2 && array1.key3 == array2[j].key3) {
array2[j] = array1[i]
break;
}
}
}
我倒觉得不是效率的问题 是你访问到一些无法访问的对象或属性 导致出现的这个吧||| 本帖最后由 mingxuan3000 于 2011-10-20 17:46 编辑
上面代码只是描述算法的,实际代码中不存在语法错误什么的。小数据量时是可以正常运行的,到上面提的的数据量时,就会产生那个对话框。
这个编辑器那个重新编辑不行。。。
|||死循环了....for(var i = 0; i < array1.length; i++) { 你的array再改变 长度也在改变 你试一下用for(var i = 0,j= array1.length;i<j; i++)这样的办法
|||因为是用key合成索引,所以可以试一下用哈希的方式 ,
如果数据量实现太多, 也可以尝试添加定时器来异步执行
- <!DOCTYPE html>
<html>
<script type="text/javascript">
var WinJS = {
update: function (a, b){
var o1 = WinJS.getKeys(a),
o2 = WinJS.getKeys(b),
k, i=0;
for(var k in o1){
if (k in o2) {
b[o2[k]] = a[o1[k]];
i++;
}
}
alert('操作完毕, 共更新' + i + '个');
},
getKeys: function (arr){
var x = arr.length, oA = {}, o;
while(x--){
o = arr[x];
oA[o.key1 + o.key2 + o.key3] = x;
}
return oA;
}
};
// 模拟数据
var array2, array1;
array2= [
{key1: 'a',key2: 'b',key3: '1'},
{key1: 'a',key2: 'b',key3: '2'},
{key1: 'a',key2: 'b',key3: '3'},
{key1: 'a',key2: 'b',key3: '4'},
{key1: 'a',key2: 'b',key3: '5'},
{key1: 'a',key2: 'b',key3: '6'},
{key1: 'a',key2: 'b',key3: '7'},
{key1: 'a',key2: 'b',key3: '8'},
{key1: 'a',key2: 'b',key3: '9'},
{key1: 'a',key2: 'b',key3: '10'},
{key1: 'a',key2: 'b',key3: '11'}
];
//模拟子集
array1 = array2.slice(2,5);
//更新
WinJS.update(array1, array2);
</script>
</html>
- <script type="text/javascript">
var interval = function(f, o) {
var _onceRunTime = 5000;//每5秒一个新的任务队列
var i = 0;
(function() {
var _st = new Date().getTime();
while(true) {
if(new Date().getTime() - _st > _onceRunTime) break;
if(!f.call(o, i)) return;
i++;
}
setTimeout(arguments.callee, 0);
})();
};
function run(i) {
document.getElementById("log").value = i;
return i<1000000;
}
function test() {
interval(run, this);
}
</script>
先谢谢大家的参与。
主要是解决 浏览器的问题,就是不要弹出那个 IE提示对话框。看来我要试试定时器了。当然我的代码里面还有很多别的处理,别的处理我也会再看看有没有问题。
现在我把 var useObj ={};加了一个 index属性
useObj.index=1//从1按顺序增加
array2中的数据完全按index排列,
这时循环array1,可以利用useObj.index属性直接定位到array2的index里面进行更新。
array1的数据如果是700可以不弹出对话框,如>700还是会弹出,我先看看定时器的方法。
大家谈谈弹出ie对话框的触发机理是什么?在什么情况下弹出这个对话框?有没有官方的解释说明。
|||看来我的标题有点不是很确切呀。现在2重循环我换成一重循环,还是不能完全解决。
当时也是页面上的元素太多了,大概好几千个link吧|||产生这种问题的主要原因是运行JS的语句太多,JS解释器长时间得不到释放,所以才弹出这种提示!
其实ff或者其他浏览器也会,只是ie一次能执行的代码句数少一些就会弹这个!
建议的解决方案两步实行:
1.改变数据结构,看你上面的var useObj ={};这个数据结构真的是烂的可以!
2.分段执行,采用定时器实现代码分段,使JS引擎有休息的时间!
针对数据结构
var useObj ={};
useObj .key1 = "a"
useObj .key2 = "b"
useObj .key3 = "x"
useObj .value1="kk"
useObj .value2="jj"
useObj .value3="cc"
useObj .value4="dd"
useObj .value5="dd"
useObj .value6="dd"
useObj .value7="dd"
这个Key假如合并掉
useObj={
key:'a,b,x',//3key合一,也没丢失你上面的信息
value:[
'kk',
'jj',
'cc',
.....
]
}
这么数据结构,key上的判断,if (array1[i].key1 == array2[j].key1&& array1[i].key2== array2[j].key2 && array1[i].key3 == array2[j].key3) {
这里就减少了2倍运算。
至于分段,楼上也有人写到!
最后,我有点 不明的是你为何这样copy来copy去的呢!
arr1和arr2中的数据都是引用类型的Object
你完全可以使用引用类型的特征来实现数据更新啊!
举个例子
var useobj={
value:1
};
arr1=[
useobj
];
arr2=[
useobj
]
这个时候,你改变arr1[0].value=2
那么arr2[0].value===2
最终我的解决方案就是
1.减少JS语句和分段JS语句
2.根据实际情况来改变功能的实现方式
||| 本帖最后由 mingxuan3000 于 2011-10-24 15:44 编辑
to:zjfeihu
不是copy来copy去,array2是页面上的总的数量,array1是页面经过后台处理(ajax),更新返回的一部分数据,他返回页面后,要更新array2
现在我来试试用setTimeOut来分段执行。
改变功能的想法也想过,但是项目马上上线了,如果改设计的话来不及了,只能先对付对付,当然这种大数据是最极端的情况(页面是根据设定动态显示的),一般的数据量是不会出这个问题的
但是据说好像上线前要进行一个评估,看能不能上线,估计极端数据量测试也是一个方面|||用setTimeOut来分段执行也不行。。。。看来瓶颈没有找对。。。|||var index = {};
function insert(key1,key2,key3,obj) {
if(!index[key1])index[key1] = {};
if(!index[key1][key2])index[key1][key2] = {};
if(!index[key1][key2][key3])index[key1][key2][key3] = obj;
}
for(var i = 0; i < array2.length; i++)
{
insert(array2[i].key1,array2[i].key2,array2[i].key3,array2[i]);
}
for(var i = 0; i < array1.length; i++)
{
var obj = index[arr1[i].key1][arr1[i].key2][arr1[i].key3];
obj.value1 = arr1[i].value1;
//...
}
|||最后问题没有解决,等解决了在来结贴
。。。|||var arr1=[],arr2=[],i=0;
function CreateObj()
{
this.key1 = "a";
this.key2 = "b";
this.key3 = "x";
this.value1 = "kk";
this.value2 = "jj";
this.value3 = "cc";
this.value4 = "dd";
this.value5 = "dd";
this.value6 = "dd";
this.value7 = "dd";
}
for(i=0;i<10000;i++)
{
arr1[i]=new CreateObj();
}
for( i=0;i<1000000;i++)
{
arr2[i]=new CreateObj();
}
for (i = 0; i < arr1.length; i++) {
for (var j = 0; j < arr2.length; j++) {
if (arr1[i].key1 == arr2[j].key1 && arr1[i].key2 == arr2[j].key2 && arr1[i].key3 == arr2[j].key3) {
arr2[j] = arr1[i];
break;
}
}
}没提示 我擦|||采自<高性能网站建设进阶指南>P102
Internet Explorer监控脚本执行的语句的数量达到最大限定值,默认为500万,就会弹出中止脚本运行的对话框
firefox检测脚本运行的总时间,当超过预定设定的时间,默认为10秒,就会弹出中止脚本运行的对话框
..|||
最好这样写:
- var aTemp = {}
aTemp["Key_Id_GuId_Name_1"] = {
value2 : "jj",
value3 : "cc",
value4 : "dd",
value5 : "dd",
value6 : "dd",
value7 : "dd"
}
aTemp["Key_Id_GuId_Name_2"] = {
value2 : "jj",
value3 : "cc",
value4 : "dd",
value5 : "dd",
value6 : "dd",
value7 : "dd"
}
for(var aKey in aTemp ) {
if ( aData[aKey] ) {
for(var aName in aData[aKey] ) {
aData[tKey][aName] = aTemp[aKey][aName]
}
} else {
//new
}
}
