等同于此功能的PHP

时间:2019-04-04 20:20:10

标签: javascript php

我有这个javascript函数,我需要将其转换为php函数

function vwap(p)
{
  if (p.length === 1 && Array.isArray(p[0])) p = p[0]
  if (!p.length) return 0
  // formula: sum(num shares * share price)/(total shares)
  return p.reduce((s,x) => s + (x[0]*x[1]), 0) / p.reduce((s,x) => s + x[0], 0) || 0;
}

到目前为止,我在下面尝试过,但被吓到了

function vwap($p) {
    if (empty($p)) {
        return 0;

        for ($p as $s) {
            //unable to understand this part in js
        }

    }

}

出于测试目的,vwap([[5, 10], [13, 8.5], [10, 11]])必须返回9.66

4 个答案:

答案 0 :(得分:3)

    function vwap($p)
    {
        if (count($p) === 1 && is_array($p[0])) {
            $p = $p[0];
        }

        if (!count($p)) {
            return 0;
        }

        return array_reduce($p, function ($s, $x) {
                return $s + ($x[0] * $x[1]);
            }, 0) / array_reduce($p, function ($s, $x) {
                return $s + $x[0];
            }, 0);
    }

1:1 php端口。

答案 1 :(得分:1)

我不太了解PHP,但是我可以解释JS及其作用,特别是reduce部件。不确定这将有多大帮助,但希望它可以让您更好地了解JS在做什么,并在您自己的PHP代码中实现

// formula: sum(num shares * share price)/(total shares)
return p.reduce((s,x)=>s+(x[0]*x[1]),0)/p.reduce((s,x)=>s+x[0],0)||0;

Array.reduce是内置的递归函数。在JS中,最简单的重写方法是:

function reduce(iterator, accumulator, reduceFunc){
  for(var i of iterator){
    accumulator = reduceFunc(accumulator, i)
  }
  return accumulator
}

这意味着p是您的迭代器,0是您的累加器,并且(s,x)=>s+(x[0]*x[1])(s,x)=>s+x[0]是您的reduce函数。因此,reduce遍历了p的每个元素,并将提供的函数称为累加器的函数(总是最后一个参数减少,因此在这种情况下,0)和当前元素p,最后返回该函数的结果,然后将其与p的下一个元素合并,或在迭代完成后返回。

我可以重写

return p.reduce((s,x) => s + (x[0]*x[1]), 0) / p.reduce((s,x) => s + x[0], 0) || 0

更多详细代码:

 // this would be the leftmost reduce function:
 function reduceNumerator(accumulator, currentItem){
   return accumulator + (currentItem[0] * currentItem[1])
 }

 // this would be the rightmost reduce function:
 function reduceDenominator(accumulator, currentItem){
   return accumulator + currentItem[0]
 }

因此,使用以下更详细的功能重写整个内容:

function vwap(p){
  if (p.length === 1 && Array.isArray(p[0])) p = p[0]
  if (!p.length) return 0

  var numerator = 0
  var denominator = 0

  for(var i of p){
    numerator = reduceNumerator(numerator, i)
    denominator = reduceDenominator(denominator, i)
  }

  return (numerator / denominator) || 0
}

如果您想轻松地验证此代码是否从您提供的输入中输出了正确的结果,请在这里摆弄小提琴:https://jsfiddle.net/q583xvra/

答案 2 :(得分:1)

使用array_reduce尽可能接近原始版本:

function vwap1(array $p): float
{
    if (count($p) === 1 && is_array($p[0])) {
        $p = $p[0];
    }

    if (count($p) === 0) {
        return 0;
    }

    $top = array_reduce($p, function(float $s, array $x): float {
        return $s + ($x[0] * $x[1]);
    }, 0);

    $bottom = array_reduce($p, function(float $s, array $x): float {
        return $s + $x[0];
    }, 0);

    if ($bottom === 0) {
        return 0;
    }

    return $top / $bottom;
}

将两次归约合并为一个foreach:

function vwap2(array $p): float
{
    if (count($p) === 1 && is_array($p[0])) {
        $p = $p[0];
    }

    if (count($p) === 0) {
        return 0;
    }

    $top = 0;
    $bottom = 0;
    foreach ($p as $x) {
        $top += $x[0] * $x[1];
        $bottom += $x[0];
    }

    if ($bottom === 0) {
        return 0;
    }

    return $top / $bottom;
}

答案 3 :(得分:1)

PHP中的预期代码:

function vwap($p) {
    if (count($p) == 1 && is_array($p[0])) {
        $p = $p[0];
    }

    if (empty($p)) {
        return 0;
    }

    // (s,x) => s + (x[0]*x[1]), 0
    $r1 = array_reduce($p, function ($s, $x) {
        return $s + $x[0] * $x[1];
    }, 0);

    // (s,x) => s + x[0], 0
    $r2 = array_reduce($p, function ($s, $x) {
        return $s + $x[0];
    }, 0);

    if (!$r1 || !$r2) {
        return 0;
    }

    return $r1 / $r2;
}

$result = vwap([[5, 10], [13, 8.5], [10, 11]]);

var_dump($result);

输出:

float(9.6607142857143)