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

2022-08-30 17:58:24

我有一个数组

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没有按预期工作?


答案 1

这是因为使用字符串比较来比较项目。从文档中array_unique

注意:当且仅当(字符串)$elem 1 === (字符串)$elem 2 时,两个元素才被视为相等。换句话说:当字符串表示相同时。将使用第一个元素。

数组的字符串表示形式只是单词,无论它的内容是什么。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 函数中获取唯一项的键(因为源数组的键被保留),并将它们从原始源数组中拉出。


答案 2

以下是@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

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

这里的诀窍是保留密钥:array_unique()

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

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

我用Google Places API遇到了它。我将多个请求的结果与不同类型的对象(think标签)相结合。但是我得到了重复,因为一个对象可以分为几个类别(类型)。并且 with 的方法不起作用,因为 attrs 是不同的,即 和 。可能这些就像临时ID。serializephoto_referencereference