• 首页
  • 移动开发
  • Web前端
  • 企业架构
  • 编程语言
  • 互联网
  • 开源软件
  • 操作系统
  • 数据库
  • 研发管理
  • 行业应用
  • 非技术
首页编程语言

音乐: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合成索引,所以可以试一下用哈希的方式 ,

如果数据量实现太多, 也可以尝试添加定时器来异步执行
    <!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>
复制代码运行代码另存代码见http://www.jatx.org/archives/122||| 本帖最后由 mingxuan3000 于 2011-10-21 10:09 编辑



先谢谢大家的参与。

主要是解决 浏览器的问题,就是不要弹出那个 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

    }

    }
复制代码运行代码另存代码
关键词:赋值数组效率

广告商赞助区

广告商赞助区

CopyRight 2009-2015


B2-20040053 Powered by Sh-Links.Com