I try to make some operations with JSON files.
For example I intend to subtract them. But the problem is there can be different key elements.
$a1=[
{"cat":2,"total":1},
{"cat":11,"total":23},
{"cat":13,"total":30}
];
$a2=[
{"cat":2,"total":15},
{"cat":11,"total":13},
{"cat":15,"total":70},
{"cat":16,"total":40}
];
and result must be
$result=[
{"cat":2,"total":14},
{"cat":11,"total":-10},
{"cat":13,"total":-30},
{"cat":15,"total":70},
{"cat":16,"total":40}
]
I have tried to take elements in a loop but I could not.
would you please show me the way to make this work ?
CodePudding user response:
First, the code:
<?php
$json1 = '[{"cat":2,"total":1},{"cat":11,"total":23},{"cat":13,"total":30}]';
$json2 = '[{"cat":2,"total":15},{"cat":11,"total":13},{"cat":15,"total":70},{"cat":16,"total":40}]';
$first = json_decode($json1, true);
$second = json_decode($json2, true);
$difference = [];
foreach ($second as $s) {
$key = null;
$f = array_filter($first, function($v, $k) use ($s, &$key){
$result = $v["cat"] === $s["cat"];
if ($result) $key = $k;
return $result;
}, ARRAY_FILTER_USE_BOTH);
$total = $s["total"] - (count($f) ? $f[$key]["total"] : 0);
$difference[]=["cat" => $s["cat"], "total" => $total];
}
foreach ($first as $f) {
$s = array_filter($second, function($v, $k) use ($f) {
return $v["cat"] === $f["cat"];
}, ARRAY_FILTER_USE_BOTH);
if (!count($s)) {
$difference[]=["cat" => $f["cat"], $total => -$f["total"]];
}
}
echo var_dump($difference); //I tested by echoing it out
Explanation:
- I initialize two variables with the JSON inputs you have defined
- I decode them both using
json_decode
and I set the second parameter totrue
to make sure they will be associative arrays - I loop the second
- I initialize the key with null
- I search for a match in the first using
$s
and$key
so I will see these variables in the closure of the function- If I find such a match then I initialize
$key
with it
- If I find such a match then I initialize
- I subtract the first total (if exists) from the total
- I add a new item with the matching category and the correct new total
- I loop the first
- I search a match in the second using
$f
- I search a match in the second using
- If no matches were found, I add the item with the matching category and negative total
In short, I loop the second and subtract the matching first if they exist, defaulting to 0 and then I loop the first to add the elements that do not have a match in the second.