Search code examples
arrayssubtraction

Inteligent subtraction of values in array (php)


PHP Language

Is it difficult to write a function to subtraction value from each [Amount] values in array ?, all that until subtraction value is appeased ?.

Example what i need (before subtraction):

[MainStockAddedArr] => Array
                        (
                            [0] => Array
                                (
                                    [Amount] => 10
                                    [Price] => 19.44
                                )

                            [1] => Array
                                (
                                    [Amount] => 15
                                    [Price] => 15.55
                                )

                            [2] => Array
                                (
                                    [Amount] => 20
                                    [Price] => 11.55
                                )

                            [3] => Array
                                (
                                    [Amount] => 30
                                    [Price] => 11.10
                                )

                        )

Value to subtraction is for example 30 pieces. So i would need to have results in array look like this:

    [MainStockAddedArr] => Array
                        (
                            [0] => Array
                                (
                                    [Amount] => 0
                                    [Price] => 19.44
                                )

                            [1] => Array
                                (
                                    [Amount] => 0
                                    [Price] => 15.55
                                )

                            [2] => Array
                                (
                                    [Amount] => 15
                                    [Price] => 11.55
                                )

                            [3] => Array
                                (
                                    [Amount] => 30
                                    [Price] => 11.10
                                )

                        )

In above example, two values are changed to 0 so that gives 25 pieces already been taken, on third value only 5 has been taken, that gives 30 pieces so no more is needed. This is just example, subtraction value will be dynamic, from a loop which is above this one.

In situation where subtraction value would be greater than in whole array (sum [Amounts]), else is needed.


Solution

  • Here is the sample of FIFO (first in first out) method.. you can try, either make some correction if needed.

    As a regular function:

    function fifo($argArray, $argValue, $colName = 'amount') {
    
        // initialize
        $total = is_numeric($argValue) ? $argValue : 0;
        $i = 0;
    
        // check for input amount (total)
        if ($total > 0) {
    
            // process the input array 
            foreach ($arrArray as $key => $v) {
    
                // initialize amount value
                $amount = $remains = $v[$colName] ?: 0;
    
                // check for amount availability
                if ($amount) {
                    // increment counter
                    $i++;
    
                    // calculate amount value remains
                    $remains -= $amount > $total ? $total : $amount;
    
                    // set amount value remains in array
                    $argArray[$key][$colName] = $remains;
    
                    // calculate last total remains
                    $total -= $amount - $remains;
    
                    // when total remains is zero then exit the loop process
                    if ($total === 0) break;
                }
            }
        }
    
        // return count of rows been used and total remains
        return ['rowsCount' => $i, 'totalRemains' => $total];
    }
    

    Usage:

    $result = fifo(<argArray>, <argValue>, [<columnName>]);
    

    As a class:

    namespace AnyNamespace;
    
    class AnyClass extend \ArrayObject {
    
    public function getFifo($argValue, $colName = 'amount') {
        return $this::fifo($this, $argValue, $colName);
    }
    
    public static function fifo($argArray, $argValue, $colName = 'amount') {
    
        // initialize
        $total = is_numeric($argValue) ? $argValue : 0;
        $i = 0;
    
        // check for input amount (total)
        if ($total > 0) {
    
            // process the input array 
            foreach ($arrArray as $key => $v) {
    
                // initialize amount value
                $amount = $remains = $v[$colName] ?: 0;
    
                // check for amount availability
                if ($amount) {
                    // increment counter
                    $i++;
    
                    // calculate amount value remains
                    $remains -= $amount > $total ? $total : $amount;
    
                    // set amount value remains in array
                    $argArray[$key][$colName] = $remains;
    
                    // calculate last total remains
                    $total -= $amount - $remains;
    
                    // when total remains is zero then exit the loop process
                    if ($total === 0) break;
                }
            }
        }
    
        // return count of rows been used and total remains
        return ['rowsCount' => $i, 'totalRemains' => $total];
    }
    }
    

    Usage:

    use AnyNamespace;
    ...
    $result = AnyClass::fifo(<argArray>, <argValue>, [<columnName>]);
    

    Or

    use AnyNamespace;
    ...
    $anyClass = new AnyClass(<inputArray>);
    
    $result = $anyClass->getFifo(<argValue>, [<columnName>]);