首页 文章

如何从PHP中的多维数组中删除重复值

提问于
浏览 248
260

如何从PHP中的多维数组中删除重复值?

示例数组:

Array
(
    [0] => Array
    (
        [0] => abc
        [1] => def
    )

    [1] => Array
    (
        [0] => ghi
        [1] => jkl
    )

    [2] => Array
    (
        [0] => mno
        [1] => pql
    )

    [3] => Array
    (
        [0] => abc
        [1] => def
    )

    [4] => Array
    (
        [0] => ghi
        [1] => jkl
    )

    [5] => Array
    (
        [0] => mno
        [1] => pql
    )

)

17 回答

  • 566

    如果你需要消除特定键上的重复项,例如mysqli id,这里有一个简单的功能

    function search_array_compact($data,$key){
        $compact = [];
        foreach($data as $row){
            if(!in_array($row[$key],$compact)){
                $compact[] = $row;
            }
        }
        return $compact;
    }
    

    Bonus Points 您可以传递一组键并添加一个外部foreach,但每个附加键的速度会慢2倍 .

  • 191

    从5.2.9开始,如果您使用 SORT_REGULAR 标志,则可以使用array_unique()

    array_unique($array, SORT_REGULAR);
    

    这使得函数比较元素的相等性,就像使用了 $a == $b 一样,这非常适合您的情况 .

    Output

    Array
    (
        [0] => Array
            (
                [0] => abc
                [1] => def
            )
    
        [1] => Array
            (
                [0] => ghi
                [1] => jkl
            )
    
        [2] => Array
            (
                [0] => mno
                [1] => pql
            )
    
    )
    

    但请记住,the documentation表示:

    array_unique()不适用于多维数组 .

  • 53

    一个易于阅读的解决方案,可能不是最有效的:

    function arrayUnique($myArray){
        if(!is_array($myArray))
            return $myArray;
    
        foreach ($myArray as &$myvalue){
            $myvalue=serialize($myvalue);
        }
    
        $myArray=array_unique($myArray);
    
        foreach ($myArray as &$myvalue){
            $myvalue=unserialize($myvalue);
        }
    
        return $myArray;
    
    }
    
  • 23

    很多人问我如何制作独特的多维数组 . 我已经从您的评论中引用了它,它对我有帮助 .

    首先,感谢@jeromegamez @daveilers提供的解决方案 . 但每当我给出答案时,他们都会问我这个'序列化'和'反序列化'是如何工作的 . 这就是为什么我想与你分享这个原因,以便它可以帮助更多的人理解这背后的概念 .

    我在解释为什么我们在步骤中使用'serialize'和'unserialize':

    Step 1: Convert the multidimensional array to one-dimensional array

    要将多维数组转换为一维数组,首先要生成数组内所有元素(包括嵌套数组)的字节流表示 . serialize()函数可以生成一个值的字节流表示 . 要生成所有元素的字节流表示,请将array_map()函数内的serialize()函数作为回调函数调用 . 无论多维数组有多少级别,结果都将是一维数组 .

    Step 2: Make the values unique

    要使这个一维数组唯一,请使用array_unique()函数 .

    Step 3: Revert it to the multidimensional array

    虽然数组现在是唯一的,但值看起来像字节流表示 . 要将其还原回多维数组,请使用unserialize()函数 .

    $input = array_map("unserialize", array_unique(array_map("serialize", $input)));
    

    再次感谢所有这一切 .

  • 18

    如果你有这样的数组

    data = array
    (
    [0] => array
    (
        [subject] => a
        [object] => c
    ),
    [1] => array
    (
        [subject] => b
        [object] => d
    ),
    [2] => array
    (
        [subject] => d
        [object] => b
    ),
    [3] => array
    (
        [subject] => d
        [object] => c
    ),
    [4] => array
    (
        [subject] => c
        [object] => a
    ),
    [5] => array
    (
        [subject] => c
        [object] => d
    )
    )
    

    你想得到这样的数组:

    data = array
    (
    [0] => array
    (
        [subject] => a
        [object] => c
    ),
    [1] => array
    (
        [subject] => b
        [object] => d
    ),
    [2] => array
    (
        [subject] => d
        [object] => c
    )
    )
    

    要么

    data = array
    (
    [0] => array
    (
        [subject] => d
        [object] => b
    ),
    [1] => array
    (
        [subject] => c
        [object] => a
    ),
    [2] => array
    (
        [subject] => c
        [object] => d
    )
    )
    

    以下代码可以提供帮助

    $data1 = array();
        $data1 = $data;
        for($q=0;$q<count($data);$q++)
        {
                for($p=0;$p<count($data1);$p++)
                {
                        if (($data[$q]["subject"] == $data1[$p]["object"]) && ($data[$q]["object"] == $data1[$p]["subject"]))
                        {
                                $data1[$p]["subject"] = $data[$q]["subject"];
                                $data1[$p]["object"] = $data[$q]["object"];
                        }
                }
        }
        $data1 = array_values(array_map("unserialize", array_unique(array_map("serialize", $data1))));
        $data = $data1;
    
  • 11

    用户对array_unique()文档的评论有很多解决方案 . 这是其中之一:

    kenrbnsn at rbnsn dot com 27-Sep-2005 12:09另一个Array_Unique用于多维数组 . 我只在二维数组上测试过它,但它可能会被推广到更多,或者使用递归 . 此函数使用serialize,array_unique和unserialize函数来完成工作 .
    function multi_unique($ array){
    foreach($ array as $ k => $ na)
    $ new [$ k] =序列化($ na);
    $ uniq = array_unique($ new);
    foreach($ uniq as $ k => $ ser)
    $ new1 [$ k] = unserialize($ ser);
    return($ new1);
    }

    这是http://ca3.php.net/manual/en/function.array-unique.php#57202 .

  • 3
    Array
    (
        [0] => Array
            (
                [id] => 1
                [name] => john
            )
    
        [1] => Array
            (
                [id] => 2
                [name] => smith
            )
    
        [2] => Array
            (
                [id] => 3
                [name] => john
            )
    
        [3] => Array
            (
                [id] => 4
                [name] => robert
            )
    
    )
    
    $temp = array_unique(array_column($array, 'name'));
    $unique_arr = array_intersect_key($array, $temp);
    

    这将从数组中删除重复的名称 . 钥匙是唯一的

  • 3

    独特多维数组的一种非常简单和合理的方法如下,

    如果您有这样的数组:

    Array
    (
        [Key1] => Array
            (
                [0] => Value1
                [1] => Value2
                [2] => Value1
                [3] => Value3
                [4] => Value1
            )
        [Key2] => Array
            (
                [0] => Value1
                [1] => Value2
                [2] => Value1
                [3] => Value3
                [4] => Value4
            )
    )
    

    使用 foreach 来解决这个问题:

    foreach($array as $k=>$v){
        $unique=array_unique($v);
        $array[$k]=$unique;
    }
    

    它会给你以下结果:

    Array
    (
        [Key1] => Array
            (
                [0] => Value1
                [1] => Value2
                [3] => Value3
            )
        [Key2] => Array
            (
                [0] => Value1
                [1] => Value2
                [3] => Value3
                [4] => Value4
            )
    )
    

    如果你想重新排列键的顺序,

    foreach($array as $k=>$v){
        $unique= array_values(array_unique($v));
        $array[$k]=$unique;
    }
    

    此操作将为您提供如下安排的键值:

    Array
    (
        [Key1] => Array
            (
                [0] => Value1
                [1] => Value2
                [2] => Value3
            )
        [Key2] => Array
            (
                [0] => Value1
                [1] => Value2
                [2] => Value3
                [3] => Value4
            )
    )
    

    我希望这会清除一切 .

  • 3

    序列化和唯一的替代方案

    $test = [
        ['abc','def'],
        ['ghi','jkl'],
        ['mno','pql'],
        ['abc','def'],
        ['ghi','jkl'],
        ['mno','pql'],
    ];
    
    $result = array_reduce(
        $test,
        function($carry,$item){
            if(!in_array($item,$carry)) {
                array_push($carry,$item);
            }
            return $carry;
        },
        []
    );
    
    var_dump($result);
    
    /*
     php unique.php
    array(3) {
        [0] =>
            array(2) {
                [0] =>
                    string(3) "abc"
                [1] =>
                    string(3) "def"
            }
        [1] =>
            array(2) {
                [0] =>
                    string(3) "ghi"
                [1] =>
                    string(3) "jkl"
            }
        [2] =>
            array(2) {
                  [0] =>
                      string(3) "mno"
                  [1] =>
                      string(3) "pql"
            }
    }
    
    • /
  • 2

    如果"remove duplicates"表示"remove duplicates, but let one there",则解决方案可能是首先在"identifier column"上应用 array_unique(...) ,然后在原始数组中删除已从列数组中删除的所有键:

    $array = [
        [
            'id' => '123',
            'foo' => 'aaa',
            'bar' => 'bbb'
        ],
        [
            'id' => '123',
            'foo' => 'ccc',
            'bar' => 'ddd'
        ],
        [
            'id' => '567',
            'foo' => 'eee',
            'bar' => 'fff'
        ]
    ];
    
    $ids = array_column($array, 'id');
    $ids = array_unique($ids);
    $array = array_filter($array, function ($key, $value) use ($ids) {
        return in_array($value, array_keys($ids));
    }, ARRAY_FILTER_USE_BOTH);
    

    结果是:

    Array
    (
        [0] => Array
            (
                [id] => 123
                [foo] => aaa
                [bar] => bbb
            )
    
        [2] => Array
            (
                [id] => 567
                [foo] => eee
                [bar] => fff
            )
    
    )
    
  • 1

    我有一个类似的问题,但我找到了100%的工作解决方案 .

    <?php
        function super_unique($array,$key)
        {
           $temp_array = [];
           foreach ($array as &$v) {
               if (!isset($temp_array[$v[$key]]))
               $temp_array[$v[$key]] =& $v;
           }
           $array = array_values($temp_array);
           return $array;
    
        }
    
    
    $arr="";
    $arr[0]['id']=0;
    $arr[0]['titel']="ABC";
    $arr[1]['id']=1;
    $arr[1]['titel']="DEF";
    $arr[2]['id']=2;
    $arr[2]['titel']="ABC";
    $arr[3]['id']=3;
    $arr[3]['titel']="XYZ";
    
    echo "<pre>";
    print_r($arr);
    echo "unique*********************
    "; print_r(super_unique($arr,'titel')); ?>
  • 1

    如果你有这样的数组:

    (users是数组的名称)

    Array=>
     [0] => (array)
       'user' => 'john'
       'age' => '23'
     [1] => (array)
      'user' => 'jane'
      'age' => '20'
     [2]=> (array)
      'user' => 'john'
      'age' => '23'
    

    并且你想删除重复...然后:

    $serialized = array();
    for ($i=0; $i < sizeof($users); $i++) { 
      $test = in_array($users['user'], $serialized);
        if ($test == false) {
          $serialized[] = $users['user'];
        }
     }
    

    可以是一个解决方案:P

  • 1

    我已经对这个问题进行了很多思考,并确定最佳解决方案应遵循两条规则 .

    • 对于可伸缩性,请在适当的位置修改数组;没有复制到新阵列

    • 为了提高性能,每次比较只应进行一次

    考虑到这一点并考虑到PHP的所有怪癖,下面是我提出的解决方案 . 与其他一些答案不同,它可以根据您想要的任何键删除元素 . 输入数组应该是数字键 .

    $count_array = count($input);
    for ($i = 0; $i < $count_array; $i++) {
        if (isset($input[$i])) {
            for ($j = $i+1; $j < $count_array; $j++) {
                if (isset($input[$j])) {
                    //this is where you do your comparison for dupes
                    if ($input[$i]['checksum'] == $input[$j]['checksum']) {
                        unset($input[$j]);
                    }
                }
            }
        }
    }
    

    唯一的缺点是迭代完成时键不按顺序排列 . 这不仅仅是使用foreach循环,但是如果你需要使用for循环,你可以在之后放置 $input = array_values($input); 上面重新编号键 .

  • 0

    这是另一种方式 . 没有保存中间变量 .

    我们使用它来删除各种重叠查询的结果 .

    $input = array_map("unserialize", array_unique(array_map("serialize", $input)));
    
  • 0

    其他方式 . 也将保留密钥 .

    function array_unique_multidimensional($input)
    {
        $serialized = array_map('serialize', $input);
        $unique = array_unique($serialized);
        return array_intersect_key($input, $unique);
    }
    
  • 0

    只需使用SORT_REGULAR选项作为第二个参数 .

    $uniqueArray = array_unique($array, SORT_REGULAR);
    
  • 0

    正如人们所说 array_unique() 非常慢,这里是我用于一级多维数组的片段 .

    $serialized_array = array_map("serialize", $input);
    
    foreach ($serialized_array as $key => $val) {
         $result[$val] = true;
    }
    
    $output = array_map("unserialize", (array_keys($result)));
    

    参考第一位用户贡献的 array_unique() function page in php.net注释

相关问题