js数组元素排队思路完美解决将浏览记录到cookie的问题
今天写js+cookie记录用户浏览文章的历史记录,考虑到使用js数组对文章ID进行排队,思路如下:如果数组中已经存在文章ID应该将其移动到队列尾部,不存在则直接添加到尾部。然后写完了js代码,感觉不是很完美,于是单独封装了一个js函数,只需要传入js数组和新增的元素,即可返回重新排好队的数组,js代码如下:
/** * 对数组重新进行排队,传入new_value在max个元素限制下 * 如果new_value存在于数组中则移动到最后,如果不存在则在最后增加 * @param Array arr js数组,参数类型[String,String,String……] * @param String new_value 新增元素,参数类型:String * @param int max 元素容量,参数类型:int * @return Array 过滤和重新排队后的数组,[String,String,String……] * @author shuiguang */ function arr_queue(arr, new_value, max){ var brr = new Array(); //除去重复和空的元素,最终元素个数小于等于max var count = 0; //使用新数组去掉旧数组的空值 var flag = false; //假设没有相同处 var same = 0; //假设相同值位于第一位 //第一个循环:去除空值和检查是否有相同值,如果有则记下索引值 for(var i=0; i<arr.length; i++){ brr[count] = arr[i]; if(brr[count] == new_value){ flag = true; same = count; } count++; if(count >= max) break; //最大不能超过max } //第二个循环:要么增加,要么移动 //思路:首先用flag判断是否有相同,如果有相同只需将其移到最前0也可以;如果没有只需增加时判断长度2种 //增加的条件是:flag==false;brr.length<max //其余的都是移动即flag==false时的满长整体后移,部分后移和flag==true时的满长整体后移,部分后移。 //但是只需要保证(移动)brr[brr.length-1]=value即可 if(flag == false && brr.length < max){ //增加 brr[brr.length] = new_value; }else{ for(var i=0; i<brr.length-1; i++){ if(i >= same){ //不管找没找到都给我前移一位,其实它是分了2种情况合并了的 brr[i] = brr[i+1]; } } brr[brr.length-1] = new_value; //目的就是移动,不会有增加的,所以只需要设置一个值 } return brr; }
由于cookie的存储空间有限,所以还添加了一个max参数,建议不要设置太大。之前在谷歌,火狐,IE8等下测试非常,唯独在IE6下测试非常怪异,后来在别人的博客里了解到IE6的cookie丢失的问题,将max调小并且清空cookie之后竟然正常了,所以上面的这个函数还是可以用的。
IE6下的bug参见这篇文章:http://www.cnblogs.com/kkun/archive/2011/07/06/2099366.html
得到排好序的js数组之后再组装成cookie字符串写入cookie,到此算是解决。后来,又增加新的功能,要求cookie里面不仅仅保存文章ID,还有其他字段,点击量什么的,不能使用简单的一维数组了,于是稍微带动了一下上面的函数,将单个元素改为数组:[主键,其他字段 对象],优化后的js代码如下:
/** * 对数组重新进行排队,传入new_value在max个元素限制下, * 如果new_value存在于数组中则移动到最后,如果不存在则在最后增加 * @param Array arr js数组,参数类型[[String, Object],[String, Object],[String, Object]……] * @param String new_value 新增元素,参数类型:[String, Object] * @param int max 元素容量,参数类型:int * @return Array 过滤和重新排队后的数组,[[String, Object],[String, Object],[String, Object]……] * @author shuiguang */ function arr_queue(arr, new_value, max){ var brr = new Array(); //除去重复和空的元素,最终元素个数小于等于max var count = 0; //使用新数组去掉旧数组的空值 var flag = false; //假设没有相同处 var same = 0; //假设相同值位于第一位 //第一个循环:去除空值和检查是否有相同值,如果有则记下索引值 for(var i=0; i<arr.length; i++){ brr[count] = arr[i]; if(brr[count][0] == new_value[0]){ flag = true; same = count; } count++; if(count >= max) break; //最大不能超过max } //第二个循环:要么增加,要么移动 //思路:首先用flag判断是否有相同,如果有相同只需将其移到最前0也可以;如果没有只需增加时判断长度2种 //增加的条件是:flag==false;brr.length<max //其余的都是移动即flag==false时的满长整体后移,部分后移和flag==true时的满长整体后移,部分后移。 //但是只需要保证(移动)brr[brr.length-1]=value即可 if(flag == false && brr.length < max){ //增加 brr[brr.length] = new_value; }else{ for(var i=0; i<brr.length-1; i++){ if(i >= same){ //不管找没找到都给我前移一位,其实它是分了2种情况合并了的 brr[i] = brr[i+1]; } } brr[brr.length-1] = new_value; //目的就是移动,不会有增加的,所以只需要设置一个值 } return brr; } console.log(arr_queue([[34,{title:"测试34",onclick:"100"}],[12,{title:"测试12",onclick:"200"}], [56,{title:"测试56",onclick:"300"}]], [78,{title:"测试56",onclick:"300"}], 5)); console.log(arr_queue([[34,{title:"测试34",onclick:"100"}],[12,{title:"测试12",onclick:"200"}], [56,{title:"测试56",onclick:"300"}]], [78,{title:"测试56",onclick:"300"}], 3)); console.log(arr_queue([[34,{title:"测试34",onclick:"100"}],[12,{title:"测试12",onclick:"200"}], [56,{title:"测试56",onclick:"300"}]], [12,{title:"测试56",onclick:"300"}], 3));
对上面改动的函数进行测试之后,可以正常运行,不过还是需要注意IE6下的cookie长度问题,到此工作问题完美解决。
========================================================================================================
根据上面的思路稍加改动便可写出响应的php版本,php代码如下:
<?php /** * 对数组重新进行排队,传入$new_value在$max个元素限制下 * 如果$new_value存在于数组中则移动到最后,如果不存在则在最后增加 * @param array arr php数组,参数类型array(array(string, mix),array(string, mix)……) * @param string new_value 新增元素,参数类型:array(string, mix) * @param int max 元素容量,参数类型:boolean(false为传入数组的长度), int(手动指定长度) * @return Array 过滤和重新排队后的数组,array(array(string, mix),array(string, mix)……) * @author shuiguang */ function arr_queue($arr, $new_value, $max = false) { if(!is_array($arr) || !is_array($new_value) || !isset($new_value[1])) { return false; } $max = ($max == false) ? count($arr) : (int)$max; $brr = array(); //除去空的元素,最终元素个数小于等于max $count = 0; //使用新数组去掉旧数组的空值 $flag = false; //假设没有相同处 $same = 0; //假设相同值位于第一位 //第一个循环:去除空值和检查是否有相同值,如果有则记下索引值 for($i=0; $i < count($arr); $i++) { $brr[$count] = $arr[$i]; if($brr[$count][0] == $new_value[0]){ $flag = true; $same = $count; } $count++; if($count >= $max) break; //最大不能超过max } //第二个循环:要么增加,要么移动 //思路:首先用flag判断是否有相同,如果有相同只需将其移到最前0也可以;如果没有只需增加时判断长度2种 //增加的条件是:flag==false;brr.length<max //其余的都是移动即flag==false时的满长整体后移,部分后移和flag==true时的满长整体后移,部分后移。 //但是只需要保证(移动)brr[brr.length-1]=value即可 if($flag == false && count($brr) < $max) //增加 { $brr[count($brr)] = $new_value; }else{ for($i=0; $i<count($brr)-1; $i++){ if($i >= $same){ //不管找没找到都给我前移一位,其实它是分了2种情况合并了的 $brr[$i] = $brr[$i+1]; } } $brr[count($brr)-1] = $new_value; //目的就是移动,不会有增加的,所以只需要设置一个值 } return $brr; } $old = array(array('first', array('a', 'b')), array('second', 'c, d'), array('third', true)); $new = arr_queue($old, array('second', 'c, d')); p($new); $new = arr_queue($old, array('second', 'c, d'), 2); p($new); function p($var) { echo "<pre>"; if($var === false) { echo 'false'; }else if($var === ''){ print_r("''"); }else{ print_r($var); } echo "</pre>"; }
简单测试了,暂未发现问题。
本文地址:http://blog.zhengshuiguang.com/php/cookie-queue.html
转载随意,但请附上文章地址:-)
评论已关闭