0

I would like te perform a calculation on the following array

$array = [
    "calculation" => [
        "add" => [
            "ceil" => [
                "multiply" => [
                    9.95,
                    "90%"
                ]
            ],
            0.95
        ]
    ]
];

eventually the calculation would traverse into:

1. add(ceil(multiply(9.95, 90%)), 0.95)
2. ceil(multiply(9.95, 90%)) + 0.95
3. ceil(8.955) + 0.95
4. 9 + 0.95
5. 9.95

I've tried recursively looping through the array using array_walk_recursive and custom functions which basically to the same. but the problem is that the add cannot calculate the ceil before it has calculated the multiply.

So how can i recusively in reversed order calculate all the parts of the array?

I'm slowly loosing my mind over this and starting to question if it's even possible.

All ideas are greatly appreciated

2
  • If you're looking for a generic solution, then we'd need to know the limits of the array structure. Can an operation only hold one other operation or can there be multiple? Is there a limit to the number of plain operands? Commented Nov 18, 2020 at 15:23
  • In theory an operand could occur multiple times like in any formula and an array could have deeper levels. If there are better ways to formulate a formula in an array or e.g. json let me know. Commented Nov 18, 2020 at 15:51

2 Answers 2

2

Another option, that verify the indexes of the array are valid functions and allows add and multiple with more than 2 values.

function multiply(...$a)
{
    return array_product($a);
}

function add(...$a)
{
    return array_sum($a);
}

function applyCalculation(array $data)
{
  $firstKey = array_keys($data)[0];
  $arguments = [];
  foreach ($data[$firstKey] as $name => $value) {
      // if argument is array with existing function, we pass it recursively
      if (function_exists($name) && is_array($value)) {
          $result = applyCalculation([$name => $value]);
          $result = is_array($result) ? $result : [$result];
          $arguments = array_merge($arguments, $result);
      } elseif (!is_array($value)) {
          // if not array, just append to arguments
          $value = strpos($value, '%') !== false ? str_replace('%','',$value) / 100 : $value;
          $arguments[] = $value;
      } elseif (is_array($value)) {
          // error here, the index is not a valid function
      }
  }

  return $firstKey(...$arguments);
}

echo applyCalculation($array['calculation']);

So it will work for your example:

$data = [
  "calculation" => [
      "add" => [
          "ceil" => [
              "multiply" => [
                  9.95,
                  '90%',
              ]
          ],
          0.95
      ]
    ]
  ];

// will give you 9.95

But it also works for more complex cases::

$array = [
  "calculation" => [
      "add" => [
          "ceil" => [
              "add" => [
                  "multiply" => [
                      9.95,
                      '90%'
                  ],
                  "add" => [
                      1,
                      3
                  ],
              ]
          ],
          0.95,
          3
      ]
  ]
];


// will give you 16.95
Sign up to request clarification or add additional context in comments.

Comments

1

Assuming that you have this structure, you may use this code. If you need more than 2 values to be "added" or "multiplied" you may need to use some splat operator or change the logic a little bit:

<?php

$array = [
    "calculation" => [
        "add" => [
            "ceil" => [
                "multiply" => [
                    9.95,
                    "90%"
                ]
            ],
            0.95
        ]
    ]
];

function add($a, $b) {
    return $a + $b;
}

function multiply($a, $b) {
    return $a * $b;
}

function calculation($arr, $operation = null) {
    
    $elements = [];
    
    foreach($arr as $k => $value) {
        if (is_numeric($k)) {
            // change % with valid numeric value
            if(strpos($value, '%')) {
                $value = str_replace('%','',$value) / 100;
            }
            //if there are no operations, append to array to evaluate under the operation
            $elements[] = $value;
        } else {
            //if there are operations, call the function recursively
            $elements[] = calculation($value, $k);
        }
    }

    if ($operation !== null) {
        return call_user_func_array($operation, $elements);
    }
    return $elements[0];
}

echo calculation($array['calculation']);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.