我需要从输入数组中删除特定列中出现重复值的行。
样本阵列:
$array = [
['user_id' => 82, 'ac_type' => 1],
['user_id' => 80, 'ac_type' => 5],
['user_id' => 76, 'ac_type' => 1],
['user_id' => 82, 'ac_type' => 1],
['user_id' => 80, 'ac_type' => 5]
];
我想按
user_id
进行过滤以确保唯一性并实现此结果:
所以,我的输出将是这样的:
[
['user_id' => 82, 'ac_type' => 1],
['user_id' => 80, 'ac_type' => 5],
['user_id' => 76, 'ac_type' => 1]
]
我已经找到了此页面,但没有一个答案适合我的情况:
$result = array_unique($array, SORT_REGULAR);
和
$result = array_map("unserialize", array_unique(array_map("serialize", $array)));
和
$result = array();
foreach ($array as $k => $v) {
$results[implode($v)] = $v;
}
$results = array_values($results);
print_r($results);
但重复行仍然存在。
为了获得更清晰的“最小、完整、可验证的示例”,我将在演示中使用以下输入数组:
$array = [
['user_id' => 82, 'ac_type' => 1],
['user_id' => 80, 'ac_type' => 5],
['user_id' => 76, 'ac_type' => 1],
['user_id' => 82, 'ac_type' => 2],
['user_id' => 80, 'ac_type' => 5]
];
// elements [0] and [3] have the same user_id, but different ac_type
// elements [1] and [4] have identical row data
无条件将行推入结果数组并分配关联的第一级键,然后使用
array_values()
重新索引。此方法会用较晚出现的行覆盖较早重复的行。
var_export(array_values(array_column($array, null, 'user_id')));
$result = [];
foreach ($array as $row) {
$result[$row['user_id']] = $row;
}
var_export(array_values($result));
输出:
[
['user_id' => 82, 'ac_type' => 2], // was input row [3]
['user_id' => 80, 'ac_type' => 5], // was input row [4]
['user_id' => 76, 'ac_type' => 1] // was input row [2]
]
使用条件或空合并赋值运算符来保留第一个出现的行,同时删除重复项。
foreach ($array as $a) {
$result[$a['user_id']] ??= $a; // only store if first occurrence of user_id
}
var_export(array_values($result)); // re-index and print
foreach ($array as $a) {
if (!isset($result[$a['user_id']])) {
$result[$a['user_id']] = $a; // only store if first occurrence of user_id
}
}
var_export(array_values($result)); // re-index and print
输出:
[
['user_id' => 82, 'ac_type' => 1], // was input row [0]
['user_id' => 80, 'ac_type' => 5], // was input row [1]
['user_id' => 76, 'ac_type' => 1] // was input row [2]
]
也可以无条件推送数据并避免条件,但输入和输出之间的行顺序可能不同(如果这对您很重要)。
var_export(array_values(array_column(array_reverse($array), null, 'user_id')));
var_export(
array_values(
array_reduce(
$array,
fn($res, $row) => array_replace([$row['user_id'] => $row], $res),
[]
)
)
);
$result = [];
foreach (array_reverse($array) as $row) {
$result[$row['user_id']] = $row;
}
var_export(array_values($result));
输出:
[
['user_id' => 80, 'ac_type' => 5], // was input row [1]
['user_id' => 82, 'ac_type' => 1], // was input row [0]
['user_id' => 76, 'ac_type' => 1] // was input row [2]
]
关于本例中未表达的边缘情况的警告:如果您使用行值作为标识符,而这些标识符在用作键时可能会被损坏,则上述技术将给出不可靠的结果。例如,PHP 不允许将浮点值作为键(它们将导致错误或被截断,具体取决于您的 PHP 版本)。只有在这些边缘情况下,您才可能考虑使用低效的迭代调用
in_array()
来评估唯一性。
仅在通过整行数据确定唯一性时才适合使用
array_unique(..., SORT_REGULAR)
。
var_export(array_unique($array, SORT_REGULAR));
输出:
[
['user_id' => 82, 'ac_type' => 1], // was input row [0]
['user_id' => 80, 'ac_type' => 5], // was input row [1]
['user_id' => 76, 'ac_type' => 1] // was input row [2]
['user_id' => 82, 'ac_type' => 2], // was input row [3]
]
作为需求的稍微扩展,如果必须基于多个列而不是所有列来确定唯一性,则使用由有意义的列值组成的“复合键”。下面使用空合并赋值运算符,但也可以实现 #2 和 #3 中的其他技术。
代码:(演示)
foreach ($array as $row) {
$compositeKey = $row['user_id'] . '_' . $row['ac_type'];
$result[$compositeKey] ??= $row; // only store if first occurrence of compositeKey
}
虽然我从未使用过它,但Ouzo Goodies 库似乎有一个与此主题相关的
uniqueBy()
方法。请参阅此处未解释的片段。
$array = [
['user_id'=>82,'ac_type'=>1],
['user_id'=>80,'ac_type'=>5],
['user_id'=>76,'ac_type'=>1],
['user_id'=>82,'ac_type'=>2],
['user_id'=>80,'ac_type'=>6]
];
$array = array_reverse($array);
$v = array_reverse(
array_values(
array_combine(
array_column($array, 'user_id'),
$array
)
)
);
echo '<pre>';
var_dump($v);
结果:
array(3) {
[0]=>
array(2) {
["user_id"]=>
int(76)
["ac_type"]=>
int(1)
}
[1]=>
array(2) {
["user_id"]=>
int(82)
["ac_type"]=>
int(1)
}
[2]=>
array(2) {
["user_id"]=>
int(80)
["ac_type"]=>
int(5)
}
}
花了我一段时间,但这应该有效(评论中的解释):
<?php
/* Example array */
$result = array(
0 => array(
"user_id" => 82,
"ac_type" => 1
),
1 => array(
"user_id" => 80,
"ac_type" => 5
),
2 => array(
"user_id" => 76,
"ac_type" => 1
),
3 => array(
"user_id" => 82,
"ac_type" => 2
),
4 => array(
"user_id" => 80,
"ac_type" => 2
)
);
/* Function to get the keys of duplicate values */
function get_keys_for_duplicate_values($my_arr, $clean = false) {
if ($clean) {
return array_unique($my_arr);
}
$dups = $new_arr = array();
foreach ($my_arr as $key => $val) {
if (!isset($new_arr[$val])) {
$new_arr[$val] = $key;
} else {
if (isset($dups[$val])) {
$dups[$val][] = $key;
} else {
//$dups[$val] = array($key);
$dups[] = $key;
// Comment out the previous line, and uncomment the following line to
// include the initial key in the dups array.
// $dups[$val] = array($new_arr[$val], $key);
}
}
}
return $dups;
}
/* Create a new array with only the user_id values in it */
$userids = array_combine(array_keys($result), array_column($result, "user_id"));
/* Search for duplicate values in the newly created array and return their keys */
$dubs = get_keys_for_duplicate_values($userids);
/* Unset all the duplicate keys from the original array */
foreach($dubs as $key){
unset($result[$key]);
}
/* Re-arrange the original array keys */
$result = array_values($result);
echo '<pre>';
print_r($result);
echo '</pre>';
?>
函数取自此问题的答案:获取数组中重复值的键
输出:
Array
(
[0] => Array
(
[user_id] => 82
[ac_type] => 1
)
[1] => Array
(
[user_id] => 80
[ac_type] => 5
)
[2] => Array
(
[user_id] => 76
[ac_type] => 1
)
)
经过测试和工作的示例。
<?php
$details = array('0'=> array('user_id'=>'82', 'ac_type'=>'1'), '1'=> array('user_id'=>'80', 'ac_type'=>'5'), '2'=>array('user_id'=>'76', 'ac_type'=>'1'), '3'=>array('user_id'=>'82', 'ac_type'=>'1'), '4'=>array('user_id'=>'80', 'ac_type'=>'5'));
function unique_multidim_array($array, $key) {
$temp_array = array();
$i = 0;
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
?>
<?php
$details = unique_multidim_array($details,'user_id');
?>
<pre>
<?php print_r($details); ?>
</pre>
将输出:
Array
(
[0] => Array
(
[user_id] => 82
[ac_type] => 1
)
[1] => Array
(
[user_id] => 80
[ac_type] => 5
)
[2] => Array
(
[user_id] => 76
[ac_type] => 1
)
)
取自此处 http://php.net/manual/en/function.array-unique.php 在用户贡献的注释中。