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'
It is possible for $b
to have matching values with different keys?
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.
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.
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! |
+------------------------+----+---------------------+---------------------------------+
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 ($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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With