PHP 比较和更改多维数组中的某些元素



简而言之,我有两个简单的数组,我想验证第二个数组中的某些键是否具有空值,并将它们替换为第一个数组中的对应值。

例:

$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

我添加了一些评论来解释,但请随时询问是否有任何不清楚的地方。

相关内容

  • 没有找到相关文章

最新更新