• php array_flip() 删除数组重复元素——大彻大悟


    1. php array_flip() 删除数组重复元素,如果用于一维索引数组,好理解。
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = array('a','b','c','a','b','b');
            var_dump(array_fliparray_flip($arr) ));
     
     
    ?>
    [root@BG-DB:~]$
    [root@BG-DB:~]$php arr.php 
    array(3) {
      [3]=>
      string(1) "a"
      [5]=>
      string(1) "b"
      [2]=>
      string(1) "c"
    }
    [root@BG-DB:~]$
    说明:
    1)array_unique() 也可以达到相同的目的,但是据说array_unique()效率很低,远不及array_flip()
    2) 据测试,上述两个函数都一般不可以用于二维数组或者关联数组,否则结果未知,例如:
    当用array_unique()用于关联数组的时候,系统应该是简单的执行了索引覆盖,所以后面的元素会覆盖前面的元素。而往往需要前面的元素不被覆盖,后面的元素丢弃。
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = array('a'=>123,'b'=>456,'c'=>'def','a'=>123,'b'=>'ccc','c'=>'abc');
            var_dump(array_unique($arr));
     
    ?>
    [root@BG-DB:~]$php arr.php 
    array(3) {
      ["a"]=>
      int(123)
      ["b"]=>
      string(3) "ccc"
      ["c"]=>
      string(3) "abc"
    }
    [root@BG-DB:~]$
    理论上如果用array_flip()执行前面的例子,就会出问题了,因为索引键值不会是一个数组。但是事实上结果确和上面一样,也是后面的覆盖前面的,可以理解。如下:
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = array('a'=>123,'b'=>456,'c'=>'def','a'=>123,'b'=>'ccc','c'=>'abc');
            var_dump(array_flip(array_flip($arr)));
     
     
    ?>
    [root@BG-DB:~]$
    [root@BG-DB:~]$php arr.php 
    array(3) {
      ["a"]=>
      int(123)
      ["b"]=>
      string(3) "ccc"
      ["c"]=>
      string(3) "abc"
    }
    [root@BG-DB:~]$
    但是,当数组维数变多的时候,上面的函数就有点难理解了,但是道理都是:后面的覆盖前面的方法去重。如下:
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = array('a'=>123,'b'=>Array("x"=>"a","y"=>'b'),'c'=>'def','a'=>123,'b'=>'ccc','c'=>'abc');
            var_dump(array_flip(array_flip($arr)));
     
     
    ?>
    [root@BG-DB:~]$php arr.php  
    array(3) {
      ["a"]=>
      int(123)
      ["b"]=>
      string(3) "ccc"
      ["c"]=>
      string(3) "abc"
    }
    [root@BG-DB:~]$
     
     
    ===============================
     
    后来干脆自己写了个多维去重的函数,是前面出现的元素不被后面覆盖,还是运行有问题。
    对于下面的数组,也就是数值键值还是一个数组,array_flip()和array_unique()就显得黔驴技穷了,如下:
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = Array( 
    Array("user"=>"wjj","age"=>20),
    Array("user"=>"wu","age"=>21),
    Array("user"=>"jun","age"=>22),
    Array("user"=>"wu","age"=>20000),
    Array("user"=>"jie","age"=>23),
    Array("user"=>"wjj","age"=>200),
    );
            var_dump(array_flip(array_flip($arr)));
            //var_dump(array_unique($arr));
     
     
    ?>
    [root@BG-DB:~]$php arr.php  
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! in /root/arr.php on line 10
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! in /root/arr.php on line 10
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! in /root/arr.php on line 10
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! in /root/arr.php on line 10
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! in /root/arr.php on line 10
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! in /root/arr.php on line 10
    array(0) {
    }
    [root@BG-DB:~]$
     
    于是自己写了个方法,一直搞不明白运行为毛还有问题,为此和boss争论的面红耳赤,代码形如:
    回来后仔细一想,就这点破事,哎!
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = Array( 
    Array("user"=>"wjj","age"=>20),
    Array("user"=>"wu","age"=>21),
    Array("user"=>"jun","age"=>22),
    Array("user"=>"wu","age"=>20000),
    Array("user"=>"jie","age"=>23),
    Array("user"=>"wjj","age"=>200),
    );
     
    $A = Array();
    foreach($arr AS &$val){
            if( isset($A[$val['user']]) ){
                    unset($val);
                    //$val = Array();
                    continue;
            }else{
                    $A[$val['user']] = true;
            }
    }
     
    var_dump($arr);
    ?>
    [root@BG-DB:~]$php arr.php 
    array(6) {
      [0]=>
      &array(2) {
        ["user"]=>
        string(3) "wjj"
        ["age"]=>
        int(20)
      }
      [1]=>
      &array(2) {
        ["user"]=>
        string(2) "wu"
        ["age"]=>
        int(21)
      }
      [2]=>
      &array(2) {
        ["user"]=>
        string(3) "jun"
        ["age"]=>
        int(22)
      }
      [3]=>
      array(2) {
        ["user"]=>
        string(2) "wu"
        ["age"]=>
        int(20000)
      }
      [4]=>
      &array(2) {
        ["user"]=>
        string(3) "jie"
        ["age"]=>
        int(23)
      }
      [5]=>
      array(2) {
        ["user"]=>
        string(3) "wjj"
        ["age"]=>
        int(200)
      }
    }
    [root@BG-DB:~]$
    上面的代码把unset($val); 改成 $val = Array(); ,后打印如下:
    [root@BG-DB:~]$
    [root@BG-DB:~]$php arr.php 
    array(6) {
      [0]=>
      &array(2) {
        ["user"]=>
        string(3) "wjj"
        ["age"]=>
        int(20)
      }
      [1]=>
      &array(2) {
        ["user"]=>
        string(2) "wu"
        ["age"]=>
        int(21)
      }
      [2]=>
      &array(2) {
        ["user"]=>
        string(3) "jun"
        ["age"]=>
        int(22)
      }
      [3]=>
      &array(0) {
      }
      [4]=>
      &array(2) {
        ["user"]=>
        string(3) "jie"
        ["age"]=>
        int(23)
      }
      [5]=>
      &array(0) {
      }
    }
    [root@BG-DB:~]$
    尼玛看上去好像是unset()不支持销毁一个多维数组,只支持销毁单一的原子元素,想了几次还真觉得是这个样子,后来测试发现不是,原来unset()支持一次性销毁一个多维数组,证据如下:
    [root@BG-DB:~]$more arr1.php 
    <?php
            $arr = Array( 
    Array("user"=>"wjj","age"=>20),
    Array("user"=>"wu","age"=>21),
    Array("user"=>"jun","age"=>22),
    Array("user"=>"wu","age"=>20000),
    Array("user"=>"jie","age"=>23),
    Array("user"=>"wjj","age"=>200),
    );
     
    unset($arr);
     
    var_dump($arr);
     
     
    ?>
    [root@BG-DB:~]$
    [root@BG-DB:~]$php arr1.php 
    PHP Notice:  Undefined variable: arr in /root/arr1.php on line 13
    NULL
    [root@BG-DB:~]$
    最后仔细想想,发现原来是这样:foreach()循环,我销毁的只是临时变量$val,而并不是真正的数组元素,即使我用&引用,只是销毁了引用指针,而实际存在数组中元素还是原封不动的,后来代码改成如下,尼玛还没达到预期结果:
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = Array( 
    Array("user"=>"wjj","age"=>20),
    Array("user"=>"wu","age"=>21),
    Array("user"=>"jun","age"=>22),
    Array("user"=>"wu","age"=>20000),
    Array("user"=>"jie","age"=>23),
    Array("user"=>"wjj","age"=>200),
    );
     
    $A = Array();
    $index = 0;
    foreach($arr AS $val){
            if( isset($A[$val['user']]) ){
                    unset($arr[$index]);
                    continue;
            }else{
                    $A[$val['user']] = true;
            }
            $index++;
    }
     
    var_dump($arr);
     
     
    ?>
    [root@BG-DB:~]$php arr.php 
    array(4) {
      [0]=>
      array(2) {
        ["user"]=>
        string(3) "wjj"
        ["age"]=>
        int(20)
      }
      [1]=>
      array(2) {
        ["user"]=>
        string(2) "wu"
        ["age"]=>
        int(21)
      }
      [2]=>
      array(2) {
        ["user"]=>
        string(3) "jun"
        ["age"]=>
        int(22)
      }
      [5]=>
      array(2) {
        ["user"]=>
        string(3) "wjj"
        ["age"]=>
        int(200)
      }
    }
    [root@BG-DB:~]$
    不解,原因是当我 unset($arr[$index]); 后而我的$index自动加1,但此时数组长度确减少了,最后的一个数组元素的下标也减少,每剔除一个元素,就会跳过一个元素。上面的代码最好用komodo单步跟踪一下,不理解为什么结果是这样的。
     
    最后改成如下,就可以了
    [root@BG-DB:~]$more arr.php 
    <?php
            $arr = Array( 
    Array("user"=>"wjj","age"=>20),
    Array("user"=>"wu","age"=>21),
    Array("user"=>"jun","age"=>22),
    Array("user"=>"wu","age"=>20000),
    Array("user"=>"jie","age"=>23),
    Array("user"=>"wjj","age"=>200),
    );
     
    $A = Array();$arrNew = Array();
    foreach($arr AS $val){
            if( isset($A[$val['user']]) ){
                    continue;
            }else{
                    $A[$val['user']] = true;
                    $arrNew[] = $val;
            }
    }
     
    var_dump($arrNew);
    ?>
    [root@BG-DB:~]$
    [root@BG-DB:~]$php arr.php  
    array(4) {
      [0]=>
      array(2) {
        ["user"]=>
        string(3) "wjj"
        ["age"]=>
        int(20)
      }
      [1]=>
      array(2) {
        ["user"]=>
        string(2) "wu"
        ["age"]=>
        int(21)
      }
      [2]=>
      array(2) {
        ["user"]=>
        string(3) "jun"
        ["age"]=>
        int(22)
      }
      [3]=>
      array(2) {
        ["user"]=>
        string(3) "jie"
        ["age"]=>
        int(23)
      }
    }
    [root@BG-DB:~]$
     
    ==========================================
    php array_flip() 删除数组重复元素
    在PHP中,用于删除数组中重复元素有一个可用的函数,那就是 array_unique(), 但是它并不是一个最高效的方法,使用array_flip() 函数将比array_uniqure()在速度上高出五倍左右。
     
    方法如下: 
    $arr = array(…………) ;//假设有一万个元素的数组,里面有重复的元素。 
    $arr = array_flip(array_flip($arr)); //这样便可以删除重复元素。 
     
    究竟是怎么回事呢?来看下array_flip()的作用:array_flip()用于将一个数组的每个元素的键和值交换,如: 
    $arr1 = array (”age” => 30, “name” => “快乐园”); 
    $arr2 = array_flip($arr1); //$arr2 就是 array(30 => “age”, “快乐园” => “name”); 
    在PHP的数组中,允许不同的元素可以取同一个值,但不允许同一个键名被不同的元素使用,如: 
    $arr1 = array (”age” => 30, “name” => “快乐园”, “age” => 20); “age” => 20将会取代”age” => 30 
    $arr1 = array (”name” => “快乐园”, “age” => 45); 
    这里 $arr1与$arr2 是相等的。 
    于是,我们便可以知道,为什么 array_flip(array_flip($arr)) 可以删除数组中重复的元素了。首先,$arr里的值会变成键名,因为值是有重复的,变成键名之后这些重复的值便成了重复的键名,PHP引擎将重复的键名删除,只保留最后一个。如: 
    $arr1 = array (”age” => 30, “name” => “快乐园”, “age” => 20); 
    $arr1 = array_flip($arr1); //$arr1 变成了 array(”快乐园” => “name”, 20 => “age”); 
    //再把 $arr1 的键名与值还复: 
    $arr1 = array_flip($arr1); 
     
    上面的代码写得简洁一些就是: $arr1 = array_flip(array_flip($arr1)); 
     
    =============================================
  • 相关阅读:
    extern C的作用详解
    UIWindow in iOS
    iOS会议和组织
    Fantageek翻译系列之《使用Autolayout显示变化高度的UITableViewCell》
    KVO的概述的使用
    Struts2 基于XML校验(易百教程)
    Maven项目中添加JDBC驱动
    org.dom4j.DocumentException: null Nested exception: null解决方法
    struts2中的数据类型自动转换
    struts2的拦截器
  • 原文地址:https://www.cnblogs.com/voiphudong/p/3366277.html
Copyright © 2020-2023  润新知