I have an array
我有一个阵列
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
)
)
)
As you can see key 0 is the same as 1,3 and 4. And key 2 is different from them all.
正如您所看到的,键0与1,3和4相同。键2与它们都不同。
When running the array_unique function on them, the only left is
当对它们运行array_unique函数时,唯一的左边是
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
)
any ideas why array_unique isn't working as expected?
任何想法为什么array_unique没有按预期工作?
5 个解决方案
#1
59
It's because array_unique
compares items using a string comparison. From the docs:
这是因为array_unique使用字符串比较来比较项目。来自文档:
Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same. The first element will be used.
注意:当且仅当(字符串)$ elem1 ===(字符串)$ elem2时,两个元素被认为是相等的。用文字表示:当字符串表示相同时。将使用第一个元素。
The string representation of an array is simply the word Array
, no matter what its contents are.
无论内容是什么,数组的字符串表示只是单词Array。
You can do what you want to do by using the following:
您可以使用以下命令执行您想要执行的操作:
$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
Here's how it works:
以下是它的工作原理:
-
Each array item is serialized. This will be unique based on the array's contents.
每个数组项都是序列化的。根据数组的内容,这将是唯一的。
-
The results of this are run through
array_unique
, so only arrays with unique signatures are left.其结果通过array_unique运行,因此只剩下具有唯一签名的数组。
-
array_intersect_key
will take the keys of the unique items from the map/unique function (since the source array's keys are preserved) and pull them out of your original source array.array_intersect_key将获取map / unique函数中唯一项的键(因为源数组的键被保留)并将它们从原始源数组中拉出。
#2
3
array_unique()
only supports multi-dimensional arrays in PHP 5.2.9 and higher.
array_unique()仅支持PHP 5.2.9及更高版本中的多维数组。
Instead, you can create a hash of the array and check it for unique-ness.
相反,您可以创建数组的哈希并检查它是否具有唯一性。
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
#3
2
Here's an improved version of @ryeguy's answer:
这是@ 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
First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.
首先,它不会进行不必要的序列化。其次,有时属性可能不同,即使ID也相同。
I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize
didn't work, since the attrs were different, namely, photo_reference
and reference
. Probably these are like temporary ids.
我使用Google Places API遇到了它。我将几个请求的结果与不同类型的对象(思考标签)结合起来。但我得到了重复,因为一个对象可能被分成几个类别(类型)。并且序列化的方法不起作用,因为attrs是不同的,即photo_reference和reference。可能这些就像临时的ids。
#4
1
array_unique deosn't work recursive, so it just thinks "this are all Array
s, let's kill all but one... here we go!"
array_unique deos不起作用递归,所以它只是认为“这是所有阵列,让我们杀掉除了一个......我们走了!”
#5
0
Quick Answer (TL;DR)
- Distinct values may be extracted from PHP Array of AssociativeArrays using foreach
- 可以使用foreach从PHP Array of AssociativeArrays中提取不同的值
- This is a simplistic approach
- 这是一种简单的方法
Detailed Answer
Context
- PHP 5.3
- PHP 5.3
- PHP Array of AssociativeArrays (tabluar composite data variable)
- PHP的AssociativeArrays数组(tabluar复合数据变量)
- Alternate name for this composite variable is ArrayOfDictionary (AOD)
- 此复合变量的备用名称是ArrayOfDictionary(AOD)
Problem
-
Scenario: DeveloperMarsher has a PHP tabular composite variable
- DeveloperMarsher wishes to extract distinct values on a specific name-value pair
- DeveloperMarsher希望在特定的名称 - 值对上提取不同的值
- In the example below, DeveloperMarsher wishes to get rows for each distinct
fname
name-value pair - 在下面的示例中,DeveloperMarsher希望为每个不同的fname名称 - 值对获取行
- 场景:DeveloperMarsher有一个PHP表格复合变量DeveloperMarsher希望在特定的名称 - 值对上提取不同的值在下面的示例中,DeveloperMarsher希望为每个不同的fname名称 - 值对获取行
Solution
-
example01 ;; DeveloperMarsher starts with a tabluar data variable that looks like this
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 can extract distinct values with a foreach loop that tracks seen values
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 );
Output result
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', ), ), )
Pitfalls
- This solution does not aggregate on fields that are not part of the DISTINCT operation
- 此解决方案不会聚合在不属于DISTINCT操作的字段上
- Arbitrary name-value pairs are returned from arbitrarily chosen distinct rows
- 从任意选择的不同行返回任意名称 - 值对
- Arbitrary sort order of output
- 任意排序顺序的输出
- Arbitrary handling of letter-case (is capital A distinct from lower-case a ?)
- 字母案件的任意处理(资本A与小写字母a不同?)
See also
- php array_intersect_key
- php array_intersect_key
- php array_flip
- php array_flip
#1
59
It's because array_unique
compares items using a string comparison. From the docs:
这是因为array_unique使用字符串比较来比较项目。来自文档:
Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same. The first element will be used.
注意:当且仅当(字符串)$ elem1 ===(字符串)$ elem2时,两个元素被认为是相等的。用文字表示:当字符串表示相同时。将使用第一个元素。
The string representation of an array is simply the word Array
, no matter what its contents are.
无论内容是什么,数组的字符串表示只是单词Array。
You can do what you want to do by using the following:
您可以使用以下命令执行您想要执行的操作:
$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
Here's how it works:
以下是它的工作原理:
-
Each array item is serialized. This will be unique based on the array's contents.
每个数组项都是序列化的。根据数组的内容,这将是唯一的。
-
The results of this are run through
array_unique
, so only arrays with unique signatures are left.其结果通过array_unique运行,因此只剩下具有唯一签名的数组。
-
array_intersect_key
will take the keys of the unique items from the map/unique function (since the source array's keys are preserved) and pull them out of your original source array.array_intersect_key将获取map / unique函数中唯一项的键(因为源数组的键被保留)并将它们从原始源数组中拉出。
#2
3
array_unique()
only supports multi-dimensional arrays in PHP 5.2.9 and higher.
array_unique()仅支持PHP 5.2.9及更高版本中的多维数组。
Instead, you can create a hash of the array and check it for unique-ness.
相反,您可以创建数组的哈希并检查它是否具有唯一性。
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
#3
2
Here's an improved version of @ryeguy's answer:
这是@ 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
First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.
首先,它不会进行不必要的序列化。其次,有时属性可能不同,即使ID也相同。
I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize
didn't work, since the attrs were different, namely, photo_reference
and reference
. Probably these are like temporary ids.
我使用Google Places API遇到了它。我将几个请求的结果与不同类型的对象(思考标签)结合起来。但我得到了重复,因为一个对象可能被分成几个类别(类型)。并且序列化的方法不起作用,因为attrs是不同的,即photo_reference和reference。可能这些就像临时的ids。
#4
1
array_unique deosn't work recursive, so it just thinks "this are all Array
s, let's kill all but one... here we go!"
array_unique deos不起作用递归,所以它只是认为“这是所有阵列,让我们杀掉除了一个......我们走了!”
#5
0
Quick Answer (TL;DR)
- Distinct values may be extracted from PHP Array of AssociativeArrays using foreach
- 可以使用foreach从PHP Array of AssociativeArrays中提取不同的值
- This is a simplistic approach
- 这是一种简单的方法
Detailed Answer
Context
- PHP 5.3
- PHP 5.3
- PHP Array of AssociativeArrays (tabluar composite data variable)
- PHP的AssociativeArrays数组(tabluar复合数据变量)
- Alternate name for this composite variable is ArrayOfDictionary (AOD)
- 此复合变量的备用名称是ArrayOfDictionary(AOD)
Problem
-
Scenario: DeveloperMarsher has a PHP tabular composite variable
- DeveloperMarsher wishes to extract distinct values on a specific name-value pair
- DeveloperMarsher希望在特定的名称 - 值对上提取不同的值
- In the example below, DeveloperMarsher wishes to get rows for each distinct
fname
name-value pair - 在下面的示例中,DeveloperMarsher希望为每个不同的fname名称 - 值对获取行
- 场景:DeveloperMarsher有一个PHP表格复合变量DeveloperMarsher希望在特定的名称 - 值对上提取不同的值在下面的示例中,DeveloperMarsher希望为每个不同的fname名称 - 值对获取行
Solution
-
example01 ;; DeveloperMarsher starts with a tabluar data variable that looks like this
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 can extract distinct values with a foreach loop that tracks seen values
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 );
Output result
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', ), ), )
Pitfalls
- This solution does not aggregate on fields that are not part of the DISTINCT operation
- 此解决方案不会聚合在不属于DISTINCT操作的字段上
- Arbitrary name-value pairs are returned from arbitrarily chosen distinct rows
- 从任意选择的不同行返回任意名称 - 值对
- Arbitrary sort order of output
- 任意排序顺序的输出
- Arbitrary handling of letter-case (is capital A distinct from lower-case a ?)
- 字母案件的任意处理(资本A与小写字母a不同?)
See also
- php array_intersect_key
- php array_intersect_key
- php array_flip
- php array_flip