比较两个数组中是否存在两个指定的值

5

我在思考如何比较以下数组的适当逻辑:

$a = [
    "ip" => [
        "1.2.3.4",
        "4.3.2.1",
    ],
    "domain" => [
        "example.com",
        "another.domain",
    ],

];

$b = [
    [
        "id"=> 136589,
        "metaname" => "ip",
        "metavalue" => "1.2.3.4",
    ],
    [
        "id"=> 136590,
        "metaname" => "domain",
        "metavalue" => "example.com",
    ],
];

我需要循环遍历 $a 来查找在 $b 中不存在的键('ip')值('1.2.3.4')组合。在数组 $a 中,我需要捕获 IP '4.3.2.1' 和域名 'another.domain'。 $b 是否可能具有不同键的匹配值?
一个好的例子是 IP 地址。可能与 IP 相关的元名称值为 'ip'、'ip.dst' 和 'ip.src'。回到示例数据 - 即使 'ip' 匹配,如果元名称不匹配,则应跳过。
foreach ($a as $metaName => $metaValues)
{
    foreach ($metaValues as $metaValue)
    {
        foreach ($b as $row)
        {
            if (in_array($metaName, $row) && in_array($metaValue, $row))
            {
                # this pair exists, move on to next $metaName-$metaValue pair
                break;
            }
            # this is where i am now, making small progress
            # more trial and error going on
        }
    }
}

在我的示例代码中,我需要帮助的地方是注释处。我尝试了各种不同的检查和循环来捕获适当的数据,但都无济于事...
  • in_array($metaValue, $row)
  • array_keys($row, $metaValue)
结合各种if语句等,但这并没有帮助。
如果我的描述没有清楚表达,也许下面的表格可以帮助一下。
+ A ---------------------+----+ B ------------------+ Comment ------------------------+
| ip, 1.2.3.4            | == | ip, 1.2.3.4         | Skip, no more checks            |
+------------------------+----+---------------------+---------------------------------+
| ip, 4.3.2.1            | != | ip, 1.2.3.4         | Keep checking                   |
|                        | != | domain, example.com | No more B to compare, I want A! |
+------------------------+----+---------------------+---------------------------------+
| domain, example.com    | != | ip, 1.2.3.4         | Keep checking                   |
|                        | == | domain, example.com | Skip, no more checks            |
+------------------------+----+---------------------+---------------------------------+
| domain, another.domain | != | ip, 1.2.3.4         | Keep checking                   |
|                        | != | domain, example.com | No more B to compare, I want A! | 
+------------------------+----+---------------------+---------------------------------+
1个回答

2

只需稍作修改并使用引用,你就能接近成功。但要小心第一个foreach,第一个参数是$metaname,但第二个参数还不是$metavalue,你需要第二个foreach循环遍历它们:

foreach ($a as $metaname => &$group) { // & is present to unset the original array
    foreach ($group as $i => $metavalue) { // here you get the distinct metavalues
        foreach ($b as $row) {
            if (!($row['metaname'] === $metaname)) {
                continue;
            }
            if ($row['metavalue'] === $metavalue) {
                unset($group[$i]);
            }
        }
    }
}

var_dump($a);

之后对$a进行var_dump()

array(2) {
  ["ip"]=>
  array(1) {
    [1]=>
    string(7) "4.3.2.1"
  }
  ["domain"]=>
  &array(1) {
    [1]=>
    string(14) "another.domain"
  }
}

第一个 foreach() 循环将访问 $a 数组的不同值,而 $metavalue 实际上是包含这些元值的数组


1
哇!即使我的代码只是部分工作,这比我原本写的完整代码好多了。非常感谢。 - user1801810

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接