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)
以下是它的工作原理:
每个数组项都是序列化的.根据数组的内容,这将是唯一的.
其结果贯穿始终array_unique
,因此只留下具有唯一签名的数组.
array_intersect_key
将从map/unique函数中获取唯一项的键(因为源数组的键被保留)并将它们从原始源数组中拉出.
这是@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_reference
和reference
。可能这些就像临时 ID。