您的位置:晶晶的博客>PHP>PHP数组唯一函数array_unique()的延伸

PHP数组唯一函数array_unique()的延伸

最近在用轻量级OOP的PHP开发框架ThinkPHP开发一套商业性网站程序,这当中又遇到了一个无法在已有知识以及框架已有类库的功能下能解决的小问题;多维数组的唯一性问题。

具体情况是这样的,TP的MySql底层读取出来的多列数据是二维数组形式,而且外维下标是数字,如果将从Mysql里读出的多列数据看做是一个数组元素的话,该二维数组是一个索引数组;var_dump()出该数组结构如图:

二维数组结构

写出来就是:array(

    array('id'=>'2','title'=>'...','ding'=>'1','jing'=>'1','time'=>'...','url'=>'...','dj'=>'...'),

    array('id'=>'2','title'=>'...','ding'=>'1','jing'=>'1','time'=>'...','url'=>'...','dj'=>'...')

);

数组的基本知识就不再多介绍了,直接说所遇到的问题;细心点的朋友或许会发现内层中的两个array是一样的,所需要解决的问题就是将该种类型的二维数组重复的元素只留下一个,多余的给unset掉;好啊,php数组不是有个array_unique()函数嘛,直接用,搞起;结果悲剧了,所有的二维数组无论有多少个均只留下了一个了,也就是说array_unique()函数作用二维数组后不是按俺们的要求进行的,问题出现了,就需要去解决;先提出了一个解决方案;函数代码如下:

function more_array_unique($arr=array()){
         foreach ($arr as $v){
             $v = join(",",$v);  //降维              
            $temp[] = $v;
         }
     $temp = array_unique($temp);    //去掉重复的字符串,也就         
    foreach ($temp as $k => $v){
            $temp[$k] = explode(",",$v);   //再将拆开的数组重新组装         
    }
        return $temp;
    }

这个函数一看就知道没有解决二维内层为关联数组的情况,直接将所有数组小标改为了数字;不太好。

function array_unique_more($arr=array()){
        foreach ($arr as $k=>$v){
            $v = join(",",$v);  //降维,也可以用implode,将一维数组转换为用逗号连接的字符串             $temp[$k] = $v;
        }
    $temp = array_unique($temp);    //去掉重复的字符串,也就是重复的一维数组     
foreach ($temp as $k => $v){
        $array=explode(",",$v); //再将拆开的数组重新组装         
        $temp2[$k]["id"] =$array[0];   
        $temp2[$k]["title"] =$array[1];
        $temp2[$k]["ding"] =$array[2];
        $temp2[$k]["jing"] =$array[3];
        $temp2[$k]["time"] =$array[4];
        $temp2[$k]["url"] =$array[5];
        $temp2[$k]["dj"] =$array[6];
    }
    return $temp2;
}

针对本文一开始的问题的解决方案出来,也达到了我想要的结果,将二维数组唯一化;但还不完美,原因很简单,因为第二函数通用性不强,哪天Mysql字段结构改变了,这个函数就不能再用了,那么是不是可以整个针对形如本文开始是图片中结构的二维数组的唯一化的函数呢?答案是肯定的,而且这种函数对ThinkPHP中从数据库中select或者find出来的具有特定结构的数据都是通吃通杀的;函数如下:

function about_unique($arr=array()){  
   /*TP数据库层读取出得二维数组内容唯一化      基本情况:将该种二维数组看成一维数组,则      该一维数组的value值有相同的则干掉只留一个,并将该一维      数组用重排后的索引数组返回,而返回的一维数组中的每个元素都是      原始key值形成的关联数组    */    
$keys =array();
   $temp = array();
   foreach($arr[0] as $k=>$arrays) {
    /*数组记录下关联数组的key值*/     
    $keys[] = $k;
   }
   //return $keys;    /*降维*/    
foreach($arr as $k=>$v) {
    $v = join(",",$v);  //降维     
    $temp[] = $v;
   }
   $temp = array_unique($temp); //去掉重复的内容    
foreach ($temp as $k => $v){
    /*再将拆开的数组按索引数组重新组装*/     
    $temp[$k] = explode(",",$v);  
   } 
   //return $temp;    /*再将拆开的数组按关联数组key值重新组装*/    
foreach($temp as $k=>$v) {
    foreach($v as $kkk=>$ck) {
     $data[$k][$keys[$kkk]] = $temp[$k][$kkk];
    }
   }
   return $data;
  }

该函数使用foreach较多,从执行效率上来说还有所欠缺,还有就是改函数还有一个致命的bug,前述为何说特定结构,就在于此,而此bug的解决还将带来更多的执行效率的降低,鉴于时间问题,今天就不再解决这个bug了,后期有机会再跟大家分享;这个bug就是特定二维数组中的字段指定的内容不能为空或者为NULL,否则使用后将会返回NULL,原因就在于join(别名:explode)函数的问题上,所以要解决带空或者NULL内容的该种类型的二维数组的唯一性问题,可以考虑加一个判断或者使用更具有精准性的preg正则来执行。

晶晶在线站长晶晶独家撰写技术文章,转载请注明来源~

转载请注明本文标题和链接:《PHP数组唯一函数array_unique()的延伸

相关推荐

哟嚯,本文评论功能关闭啦~

  1. #1

    其实你可以不用这么麻烦,encode json一下降维,然后再array_unique,然后再decode json就可以了

    思思 10年前 (2014-07-15) 回复
    • @思思:嗯,这篇文章已经很老了,后来业务代码中处理就是采用你说的方式;当年被关联数组跟索引数组给拌着了,那个时候我也只是一只菜鸟(现在依然是菜鸟,只不过人老了),为了处理能同时处理关联数组与索引数组只好无限制的foreach

      晶晶 10年前 (2014-07-28) 回复