简而言之,我有两个简单的数组,我想验证第二个数组中的某些键是否具有空值,并将它们替换为第一个数组中的对应值。
例:
$a1 = [ 1 => 'one', 2 => 'two', 3 => 'three',5=>'cinco', 6=>'six'];
$a2 = [ 2 => 'two', 5=>'five', 6=>'' ];
结果:
Array
(
[2] => two
[5] => five
[6] => six
)
以下代码已经适用于此。
$keys = array_keys($a1);
foreach ($keys as $k)
{
if ((isset($a2[$k])) && (($a2[$k]) == '')) {
$a2[$k] = $a1[$k];
}
}
print_r($a2);
但是,如果我们想将其应用于两个 2D 数组怎么办?在这种情况下,正确的方法是什么?假设这两个 2D 数组将是:
$superheroes_complete = array(
"spiderman" => array(
"name" => "Peter Parker",
"email" => "peterparker@mail.com",
),
"superman" => array(
"name" => "Clark Kent",
"email" => "clarkkent@mail.com",
),
"ironman" => array(
"name" => "Harry Potter",
"email" => "harrypotter@mail.com",
)
);
$superheroes_empty = array(
"spiderman" => array(
"name" => "Peter Parker",
"email" => "",
),
"superman" => array(
"name" => "Clark Kent",
"email" => "something",
),
"ironman" => array(
"name" => "Harry Potter",
"email" => "another one",
)
);
期望:
$superheroes = array(
"spider-man" => array(
"name" => "Peter Parker",
"email" => "peterparker@mail.com",
),
"super-man" => array(
"name" => "Clark Kent",
"email" => "something",
),
"iron-man" => array(
"name" => "Harry Potter",
"email" => "another one",
)
);
非常感谢,提前感谢您!
您已经为数据添加了另一个级别,因此您也可以使用第二个foreach
循环向检查添加另一个级别:
foreach ($superheroes_complete as $hero => $info) {
foreach ($info as $key => $value) {
if (empty($superheroes_empty[$hero][$key])) {
$superheroes_empty[$hero][$key] = $value;
}
}
}
首先请注意,您的一维案例可以简化:
foreach ($a2 as $k => $v) {
if (!isset($v)) {
$a2[$k] = $a1[$k];
}
}
然后对于 2D 情况,假设第一级键总是相同的(或者它成为一个完全不同的问题!
foreach ($superheroes_complete as $main_k => $main_v) {
foreach ($main_v as $k => $v) {
if (!isset($v)) {
$superheroes_empty[$main_k][$k] = $superheroes_complete[$main_k][$k];
}
}
如果您只需要处理"电子邮件"字段,则可以这样做:
<?php
$keys = array_keys($superheroes_complete);
foreach ($keys as $k)
{
if ((isset($superheroes_empty[$k]["email"])) &&
(($superheroes_empty[$k]["email"]) == '')) {
$superheroes_empty[$k]["email"] = $superheroes_complete[$k]["email"];
}
}
var_dump($superheroes_empty);
?>
对于嵌套深度不受限制的通用情况,您可以使用此递归函数:
function fillEmpty(&$filled, &$empty) { // arguments are by reference
if ($empty === "") {
$empty = $filled;
return;
}
if (!is_array($filled) || !is_array($empty)) return;
foreach ($filled as $key => $value) {
if (isset($empty[$key])) fillEmpty($value, $empty[$key]);
}
}
调用示例:
fillEmpty($superheroes_complete, $superheroes_empty);
这将修改第二个参数,填充空值。
查看它在 eval.in 上运行
这可能是你的幸运日,php 有一些内置函数来比较数组值和键。使用可以比较两个或多个数组并返回差值的array_diff()
。您也可以使用相反的array_intersect()
。
如果只想比较键,请使用仅返回键差异的array_diff_key()
或返回匹配键的array_intersect_key()
。
你也可以考虑一个递归解决方案。这适用于 1D 和 2D 数组,甚至是 N 维数组。
我知道应该谨慎使用递归,因为它可能非常耗费资源。然而,这是一个更通用的解决方案,并且通过更少的嵌套控制结构和早期返回保持代码更简洁,我发现这更易读。我将使用本机array_walk
方法,因为我被教导它应该比 php 循环表现得更好。
所以这就是我的代码的样子:
function array_complement_recursive(&$partial, $complete) {
array_walk($partial, function(&$value, $key) use ($complete) {
// (for safety) complete does not contain matching key: done
if (! array_key_exists($key, $complete)) {
return;
}
// value is array: call recursive
if (is_array($value)) {
array_complement_recursive($value, $complete[$key]);
return;
}
// value is not 'empty': done
// note that null, 0, false will also not match, you may want to make
// this check more specific to match only the empty string
if ($value) {
return;
}
$value = $complete[$key];
});
}
我已经设置了一个小演示,以便您可以看到它适用于您的两个示例。正如我所说,它甚至应该适用于具有更多维度或更不规则结构的数组。
http://phpfiddle.org/main/code/49iz-vrwg
我添加了一些评论来解释,但请随时询问是否有任何不清楚的地方。