Search code examples
phparraysdiffsubtractioncontinue

PHP consecutive subtraction two arrays


I have 2 arrays like this

a = Array([101] => 5,[109] =>100,[220] => 50,[231] => 45,[245] => 90)
b = Array(['PRO'] => 12,['LOG'] => 15,['DEV'] => 100)

I want to consecutive subtract 2 array and result like this

c = Array([101] => 0,[109] => 0, [220] => 28, [231] => 45,  [245] => 90)

Explain: I assumed used foreach to get value of a and b

1st: 5-12=0(move 7 to next time) <=> c[101] => 0;
2nd: 100-7 = 93 (7 at 1st)
3rd : 93-15 = 78
4th: 78-100 = 0 (move 22 to 5th time) <=> c[109] => 0
5th: 50-22 = 28 <=> c[220] => 28

But I don't know how to express in PHP


Solution

  • I'll try to rephrase your requirements, because I had to read your question about 10 times before I understood what you needed.

    You want to reduce the values in $a (using subtraction) by consuming the values in $b in the order by which the associative elements occur. When a value in $b is large enough to reduce the value in $a to zero or lower, you want to set the $a value to zero and carry the remaining value (difference) to the subtraction of the next value in $a. This carried value must be consumed by one or more values in $a until it is depleted. When a carried value is depleted, then the next occurring value in $b should be used to reduce the current value in $a.

    • 12($b[PRO]) is used to reduce 5($a[101]) to 0(new $a[101]) then 7 becomes the carried value and the next value in $a will be the new focus.
    • 100($a[109]) is first reduce by 7(carried) and becomes 93(new $a[109).
    • 93(new [109]) is then reduced again by 15($b[LOG]) and becomes 78(new [109]).
    • 78(new [109]) is then reduced again by 100($b[DEV]) flooring the value to 0, making a new carried value of 22, and moving focus to $a[220].
    • 50($a[220]) is reduced by 22(carried) making 28(new $a[220]).
    • At this point, the carried value is depleted AND there are no more values in $b to reduce $a values by.
    • $a[231] and $a[245] remain unchanged because there are no remaining values to subtract with.

    My snippet uses text book arithmetic jargon: minuend - suprahend = difference.
    The $difference is what is carried.
    array_shift() is appropriate because it consumes the values in $b as they are accessed.

    Code: (Demo)

    $a = [
        101 => 5,
        109 => 100,
        220 => 50,
        231 => 45,
        245 => 90
    ];
    $b = [
        'PRO' => 12,
        'LOG' => 15,
        'DEV' => 100
    ];
    
    $difference = 0;
    foreach ($a as &$minuend) {
        while ($minuend && ($b || $difference < 0)) {
            $suprahend = $difference < 0 ? -$difference : array_shift($b);
            $difference = $minuend - $suprahend;
            $minuend = max(0, $difference);
        }
    }
    var_export($a);
    

    Output:

    array (
      101 => 0,
      109 => 0,
      220 => 28,
      231 => 45,
      245 => 90,
    )