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

dot*_*tty 18 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
    )

)
Run Code Online (Sandbox Code Playgroud)

)

正如您所看到的,键0与1,3和4相同.键2与它们都不同.

在它们上运行array_unique函数时,唯一的左边是

Array (
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )
)
Run Code Online (Sandbox Code Playgroud)

)

任何想法为什么array_unique没有按预期工作?

rye*_*guy 63

这是因为array_unique使用字符串比较来比较项目.来自文档:

注意:当且仅当(字符串)$ 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
Run Code Online (Sandbox Code Playgroud)

以下是它的工作原理:

  1. 每个数组项都是序列化的.根据数组的内容,这将是唯一的.

  2. 其结果贯穿始终array_unique,因此只留下具有唯一签名的数组.

  3. array_intersect_key 将从map/unique函数中获取唯一项的键(因为源数组的键被保留)并将它们从原始源数组中拉出.


x-y*_*uri 7

这是@ryeguy 答案的改进版本:

<?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
Run Code Online (Sandbox Code Playgroud)

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

这里的技巧是array_unique()保留密钥:

$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [3]=>
  int(3)
}
Run Code Online (Sandbox Code Playgroud)

让我们array_intersect_key()留下所需的元素。

我在Google Places API中遇到过这个问题。我将多个请求的结果与不同类型的对象(想想标签)结合起来。但我得到了重复项,因为一个对象可以分为多个类别(类型)。并且 方法serialize不起作用,因为属性不同,即photo_referencereference。可能这些就像临时 ID。