zoukankan      html  css  js  c++  java
  • 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)); 
     
    =============================================
  • 相关阅读:
    Python使用SMTP模块、email模块发送邮件
    harbor搭建及使用
    ELK搭建-windows
    ELK技术栈之-Logstash详解
    【leetcode】1078. Occurrences After Bigram
    【leetcode】1073. Adding Two Negabinary Numbers
    【leetcode】1071. Greatest Common Divisor of Strings
    【leetcode】449. Serialize and Deserialize BST
    【leetcode】1039. Minimum Score Triangulation of Polygon
    【leetcode】486. Predict the Winner
  • 原文地址:https://www.cnblogs.com/voiphudong/p/3366277.html
Copyright © 2011-2022 走看看