比较两个数组的两个数组

时间:2021-10-08 12:01:56

I'm struggling with the appropriate logic to compare the following arrays:

我正在努力使用适当的逻辑来比较以下数组:

$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",
    ],
];

I need to loop over $a to find the key ('ip') value ('1.2.3.4') combinations that do not exist in $b. In the array $a, I need to capture the ip '4.3.2.1' and the domain 'another.domain'

我需要遍历$ a来找到$ b中不存在的密钥('ip')值('1.2.3.4')组合。在数组$ a中,我需要捕获ip'4.3.2.1'和域'another.domain'

It is possible for $b to have matching values with different keys?

$ b可以使用不同的键匹配值吗?

A good example is that of 'ip' addresses. Possible IP-related metaname values are 'ip', 'ip.dst' and 'ip.src'. Back to the sample data - even if the 'ip' matches, if the metaname does not match it should be skipped.

'ip'地址就是一个很好的例子。可能与IP相关的元名值为'ip','ip.dst'和'ip.src'。返回示例数据 - 即使'ip'匹配,如果metaname不匹配,也应该跳过它。

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 my sample code the comment is where I need help. I've tried various iterations of different checks and loops to capture the appropriate data to no avail...

在我的示例代码中,评论是我需要帮助的地方。我已经尝试了不同的检查和循环的各种迭代来捕获适当的数据无济于事......

  • in_array($metaValue, $row)
  • array_keys($row, $metaValue)

combined with various if statements and so on but that won't help.

结合各种if语句等,但这无济于事。

In the event that my description failed to be clear maybe the following table will help.

如果我的描述未能清楚,则下表可能有所帮助。

+ 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 个解决方案

#1


2  

With just a slight modification and the use of a reference you are pretty close. But be careful with the first foreach, the first argument is a $metaname, but the second is not yet the $metavalue, you need a second foreach to loop over them:

只需稍加修改并使用参考,您就会非常接近。但要注意第一个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() of $a afterwards

之后$ a的var_dump()

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

The first foreach() would access the distinct values of $a arrays whereas $metavalue is in fact the array containing those metavalues.

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

#1


2  

With just a slight modification and the use of a reference you are pretty close. But be careful with the first foreach, the first argument is a $metaname, but the second is not yet the $metavalue, you need a second foreach to loop over them:

只需稍加修改并使用参考,您就会非常接近。但要注意第一个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() of $a afterwards

之后$ a的var_dump()

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

The first foreach() would access the distinct values of $a arrays whereas $metavalue is in fact the array containing those metavalues.

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