如何在数组数组上使用array_unique?

时间:2010-04-01 14:50:58

标签: php arrays array-unique

我有一个数组

Array(
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[1] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[2] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 8
        [frame_id] => 8
    )

[3] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[4] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

)

正如您所见,键0与1,3和4相同。键2与它们都不同。

当对它们运行array_unique函数时,唯一的左边是

Array (
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )
)

为什么array_unique没有按预期工作?

7 个答案:

答案 0 :(得分:63)

这是因为array_unique使用字符串比较来比较项目。来自docs

  

注意:考虑两个要素   等于且仅当(字符串)$ elem1   ===(字符串)$ elem2。用文字表示:当字符串表示相同时。   将使用第一个元素。

数组的字符串表示只是单词Array,无论其内容是什么。

您可以使用以下内容执行您想要执行的操作:

$arr = array(
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 8)
);

$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'user' => int 3
  2 => 
    array
      'user_id' => int 33
      'user' => int 8

以下是它的工作原理:

  1. 每个数组项都是序列化的。这个 将基于阵列的独特性 内容。

  2. 此结果通过array_unique运行, 所以只有具有唯一的数组 留下签名。

  3. array_intersect_key将采取 来自的独特项目的关键 map / unique函数(因为源数组的键被保留)和pull 它们不属于原始来源 阵列

答案 1 :(得分:3)

array_unique()仅支持PHP 5.2.9及更高版本中的多维数组。

相反,您可以创建数组的哈希并检查它是否具有唯一性。

$hashes = array(); 

foreach($array as $val) { 
    $hashes[md5(serialize($val))] = $val; 
} 

array_unique($hashes);

答案 2 :(得分:2)

以下是@ryeguy's answer的改进版本:

<?php

$arr = array(
    array('user_id' => 33, 'tmp_id' => 3),
    array('user_id' => 33, 'tmp_id' => 4),
    array('user_id' => 33, 'tmp_id' => 5)
);


# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
    return $el['user_id'];
}, $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'tmp_id' => int 3

首先,它不会进行不必要的序列化。其次,有时属性可能不同,即使ID也相同。

我用Google Places API遇到了它。我将几个请求的结果与不同类型的对象(思考标签)结合起来。但我得到了重复,因为一个对象可能被分为几个类别(类型)。使用serialize的方法不起作用,因为attrs不同,即photo_referencereference。可能这些就像临时的ids。

答案 3 :(得分:1)

array_unique deos不起作用递归,所以它只是认为“这都是Array s,让我们除了一个之外杀了所有......我们走吧!”

答案 4 :(得分:0)

快速回答(TL; DR)

  • 可以使用foreach
  • 从PHP Array of AssociativeArrays中提取不同的值
  • 这是一种简单的方法

详细答案

上下文

  • PHP 5.3
  • PHP的AssociativeArrays数组(tabluar复合数据变量)
  • 此复合变量的备用名称为ArrayOfDictionary(AOD)

问题

  • 场景: DeveloperMarsher有一个PHP表格复合变量
    • DeveloperMarsher希望在特定的名称 - 值对
    • 上提取不同的值
    • 在下面的示例中,DeveloperMarsher希望为每个不同的fname名称 - 值对获取行

解决方案

  • example01 ;; DeveloperMarsher以一个类似于

    的tabluar数据变量开头
    $aodtable = json_decode('[
    {
      "fname": "homer"
      ,"lname": "simpson"
    },
    {
      "fname": "homer"
      ,"lname": "jackson"
    },
    {
      "fname": "homer"
      ,"lname": "johnson"
    },
    {
      "fname": "bart"
      ,"lname": "johnson"
    },
    {
      "fname": "bart"
      ,"lname": "jackson"
    },
    {
      "fname": "bart"
      ,"lname": "simpson"
    },
    {
      "fname": "fred"
      ,"lname": "flintstone"
    }
    ]',true);
    
  • example01 ;; DeveloperMarsher可以使用跟踪看到值的foreach循环提取不同的值

    $sgfield  =   'fname';
    $bgnocase =   true;
    
    //
    $targfield  =   $sgfield;
    $ddseen     =   Array();
    $vout       =   Array();
    foreach ($aodtable as $datarow) {
    if( (boolean) $bgnocase == true ){ @$datarow[$targfield] = @strtolower($datarow[$targfield]); }
    if( (string) @$ddseen[ $datarow[$targfield] ] == '' ){
      $rowout   = array_intersect_key($datarow, array_flip(array_keys($datarow)));
      $ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
      $vout[] = Array( $rowout );
    }
    }
    //;;
    
    print var_export( $vout, true );
    

输出结果

array (
  0 =>
  array (
    0 =>
    array (
      'fname' => 'homer',
      'lname' => 'simpson',
    ),
  ),
  1 =>
  array (
    0 =>
    array (
      'fname' => 'bart',
      'lname' => 'johnson',
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'fname' => 'fred',
      'lname' => 'flintstone',
    ),
  ),
)

陷阱

  • 此解决方案不会在不属于DISTINCT操作的字段上聚合
  • 从任意选择的不同行返回任意名称 - 值对
  • 输出的任意排序顺序
  • 信件案件的任意处理(资本A与小写字母a不同?)

另见

  • php array_intersect_key
  • php array_flip

答案 5 :(得分:0)

function array_unique_recursive($array)
{
    $array = array_unique($array, SORT_REGULAR);

    foreach ($array as $key => $elem) {
        if (is_array($elem)) {
            $array[$key] = array_unique_recursive($elem);
        }
    }

    return $array;
}

那不行吗?

答案 6 :(得分:0)

`

    $arr = array(
        array('user_id' => 33, 'tmp_id' => 3),
        array('user_id' => 33, 'tmp_id' => 4),
        array('user_id' => 33, 'tmp_id' => 3),
        array('user_id' => 33, 'tmp_id' => 4),
    );
    $arr1 = array_unique($arr,SORT_REGULAR);
    echo "<pre>";
    print_r($arr1);
    echo "</pre>";
   Array(   
        [0] => Array(
                    [user_id] => 33
                    [tmp_id] => 3
        )
        [1] => Array(
                     [user_id] => 33
                     [tmp_id] => 4
          )
        )
    

`