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)); 
 
=============================================


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM