我在不同的数组中得到具有重复值的三维数组,我想将这个三维数组合并到一个数组中,并删除最终数组中的重复值。
我的数组是:
repo/public/index.html
我尝试了以下解决方案,但没有工作:
Array
(
[0] => Array
(
[0] => Array
(
[role_id] => 2
[name] => name1
[email] => email1@somemail.com
)
[1] => Array
(
[role_id] => 2
[name] => name2
[email] => email2@somemail.com
)
[2] => Array
(
[role_id] => 2
[name] => name3
[email] => email3@somemail.com
)
)
[1] => Array
(
[0] => Array
(
[role_id] => 2
[name] => name4
[email] => email4@somemail.com
)
[1] => Array
(
[role_id] => 2
[name] => name3
[email] => email3@somemail.com
)
)
[2] => Array
(
[0] => Array
(
[role_id] => 2
[name] => name3
[email] => email3@somemail.com
)
[1] => Array
(
[role_id] => 2
[name] => name2
[email] => email2@somemail.com
)
)
[3] => Array
(
[0] => Array
(
[role_id] => 2
[name] => name3
[email] => email3@somemail.com
)
)
)
我想将此数组合并为一个单维数组,并从中删除重复值。我可以通过循环遍历每个数组得到结果,但执行时间会更多,我希望必须有一些简单的解决方案。任何人都可以解决这个问题,谢谢。
答案 0 :(得分:0)
请尝试此代码
$list = is your array;
$flattern_array = array();
$flat_array = function($item) use(&$flattern_array, &$flat_array){
$keys = array_keys($item);
if(is_array($item) && !in_array("role_id", $keys, TRUE)){
foreach($item as $_item){
$flat_array($_item);
}
}else{
$flattern_array[] = $item;
}
};
$flat_array($list);
// Now $flattern_array have all items
//Here we can remove duplicates from array
$result = array_map("unserialize", array_unique(array_map("serialize", $flattern_array)));
答案 1 :(得分:0)
我们不是为这个数据集编写纯粹的自定义解决方案,而是首先创建一些通用函数,这样可以更方便地处理数据的一般术语
我们从flatten
函数开始,该函数采用N
维数组并返回N-1
维数组。
function flatten (array $xs) {
return array_reduce
( $xs
, 'array_merge'
, []
)
;
}
var_export (flatten ($data));
// array (
// 0 =>
// array ( 'role_id' => 2, 'name' => 'name1', 'email' => 'email1@somemail.com', ),
// 1 =>
// array ( 'role_id' => 2, 'name' => 'name2', 'email' => 'email2@somemail.com', ),
// 2 =>
// array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
// 3 =>
// array ( 'role_id' => 2, 'name' => 'name4', 'email' => 'email4@somemail.com', ),
// 4 =>
// array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
// 5 =>
// array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
// 6 =>
// array ( 'role_id' => 2, 'name' => 'name2', 'email' => 'email2@somemail.com', ),
// 7 =>
// array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
// )
现在如果我们可以使用PHP的array_unique
会很好,但它只适用于原始值。在这种情况下,我们需要一个允许我们指定更复杂的匹配行为的函数。为此,我们制作了自己的array_unique_by
函数
function array_unique_by (array $xs, callable $f) {
return array_reduce
( $xs
, function ($acc, $x) use ($f) {
if ( array_search_by ( $acc
, function ($y) use ($f, $x) {
return call_user_func ($f, $x, $y);
}
)
=== null
)
return array_merge ($acc, [ $x ]);
else
return $acc;
}
, []
)
;
}
在我们进一步发展之前,请注意我们已经介绍了array_search_by
。与PHP的array_unique
一样,PHP的array_search
也适用于原始值,因此我们需要一种方法来搜索复杂的值,比如数据集中的值。
function array_search_by (array $xs, callable $f) {
foreach ($xs as $x) {
if (call_user_func($f, $x) === true)
return $x;
}
return null;
}
最后,为了让我们使用array_unique_by
函数,我们需要传递匹配函数。此函数将告诉array_unique_by
我们数据集的哪些元素被视为“匹配”。例如,我们将此称为match_user
,因为您的数据集中的元素看起来像是用户。
function match_user ($a, $b) {
return $a["role_id"] === $b["role_id"]
&& $a["name"] === $b["name"]
&& $a["email"] === $b["email"]
;
}
一切就绪后,我们现在可以编写一个非常简单的程序来实现您想要的结果
var_export (array_unique_by (flatten ($data), 'match_user'));
// array (
// 0 =>
// array ( 'role_id' => 2, 'name' => 'name1', 'email' => 'email1@somemail.com', ),
// 1 =>
// array ( 'role_id' => 2, 'name' => 'name2', 'email' => 'email2@somemail.com', ),
// 2 =>
// array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
// 3 =>
// array ( 'role_id' => 2, 'name' => 'name4', 'email' => 'email4@somemail.com', ),
// )
<强>备注强>
上述函数是用函数式编写的,在PHP中很难表达。我很难找到array_unique_by
找到合适的语法格式。关键是,您可以根据需要实现这些通用功能。这是使用命令式样式的array_unique_by
的另一种可能实现,这对PHP程序员来说更为熟悉。此实现与上面定义的版本完全相同,但可能更好地向读者传达其意图
function array_unique_by (array $xs, callable $f) {
$acc = [];
foreach ($xs as $x) {
$match =
array_search_by
( $acc
, function ($y) use ($f, $x) {
return call_user_func ($f, $x, $y);
}
)
;
if ($match === null)
array_push ($acc, $x);
}
return $acc;
}
最后,PHP anonymous functions的lambda语法也非常流行。为了利用在lambda之外定义的变量,我们必须使用这种笨拙的use ($f, $x)
语法。我们可以使用其他通用帮助函数来解决这个问题,例如下面介绍的partial
function partial (callable $f, ...$xs) {
return function (...$ys) use ($f, $xs) {
return call_user_func_array
( $f
, array_merge ($xs, $ys)
)
;
};
}
function array_unique_by (array $xs, callable $f) {
$acc = [];
foreach ($xs as $x) {
$match =
array_search_by
( $acc
, partial ($f, $x)
)
;
if ($match === null)
array_push ($acc, $x);
}
return $acc;
}
上面,array_unique_by
与其他实现完全相同,但更容易阅读。你可以继续使用它直到你开心。
这里的想法很简单:你可以使用泛型函数创建缺失的特征或抽象出烦恼。然后可以以各种优雅的方式组合这些功能,从而使读者更容易理解的程序。
<强>性能强>
我们的array_unique_by
函数使用我们自己的array_search_by
函数。如果我们在心理上可视化正在进行的过程,我们输入中的每个元素都需要与我们正在构建的输出$acc
进行比较。我们在这里进行的“找到匹配”是通过在$acc
的开头搜索并逐个查看每个元素来完成的,直到找到潜在的匹配...
如果我们的输入数据非常大,则此linear search的性能配置文件非常糟糕。优化此方法的一种方法是将$acc
改为binary search tree。但当然这意味着我们必须创建一个适合我们数据集的。或许我们可以利用PHP的hashable接口来减少工作量。这样的实现受益于二进制搜索,它比线性搜索快得多。
本练习留待读者阅读。