当foreach中的函数遇到一个非常好的数值

时间:2018-01-30 00:13:35

标签: php arrays

出于某种原因,当我尝试循环数组并更改它的值时,我会不断收到此通知。

由于某种原因,数组传递了2个值,前一个值和后一个值在运行改变值的相同函数时。

class UnitConverter {

    public $vulgar_to_float = array('½' => '1/2');

    public function replaceUnicode($amount){
        foreach($this->vulgar_to_float as $key => $float){
            if(is_numeric($amount)){
                return $amount;
            } else if($key === $amount){
                return $float;
            }
        }
    }

    public function convertAmount($amount, $from, $to){
        if($from === 'pound' && $to === 'ounce'){
            return $amount * 16;
        } else if($from === 'cup' && $to === 'tablespoon'){

            print_r($amount); // here it's echoing 2 values when it should be 1

            return $this->replaceUnicode($amount) * 16;
        } else {
            throw new \Exception('Unable to convert ' . $from . ' to ' . $to);
        }
    }
}


function convertIngredients($arr){
    foreach($arr as $key => $value){
        if($arr[$key]['unit_name'] === 'pound'){
            $arr[$key]['amount'] = (new UnitConverter())->convertAmount($arr[$key]['amount'], 'pound', 'ounce');
            $arr[$key]['unit_name'] = 'ounce';
        } else if($arr[$key]['unit_name'] === 'cup'){
            $arr[$key]['amount'] = (new UnitConverter())->convertAmount($arr[$key]['amount'], 'cup', 'tablespoon');
            $arr[$key]['unit_name'] = 'tablespoon';
        }
    }

    return $arr;
}


function generateBreakfast(){
    $array = $var = array(
        0 => array( 'amount' => 1, 'ingredient_name' => 'almond flour', 'unit_name' => 'cup' ),
        1 => array( 'amount' => ½, 'ingredient_name' => 'erythritol', 'unit_name' => 'cup' ),
        2 => array( 'amount' => 1, 'ingredient_name' => 'egg', 'unit_name' => 'large' )
    );

    $converted_ingredients = convertIngredients($array);

    return $converted_ingredients;
}

echo '<pre>';
print_r(generateBreakfast());
echo '</pre>';

所以在convertIngredients中,我们调用了convertAmount方法,但由于某种原因,它传递了这个'1½',而不是每次迭代都单独调用该方法。

如果你看一下这里:https://eval.in/944452,赤藓糖醇的含量显示为16,但它应为8,因为16 = 1的1/2 = 8。

2 个答案:

答案 0 :(得分:4)

vulgar_to_float替换为...

public $vulgar_to_float = array('½' => 0.5);

......而且should work

目前,16 * '1/2'表达式由代码评估。您可能希望PHP能够自动解析&#39;第二个操作数到正确的数值。但它没有,因为解析规则(应用于字符串以试图将其转换为数字)don't treat '/' character in any special way - 因此它被丢弃,以及其余的字符串。

这意味着,16 * '1/2'的值为essentially equal16 * 1 - 正如您清楚注意到的那样,这是16。

此更改可防止此错误 - 并使PHP的生命更容易一些:如果您要获得replaceUnicode返回值的浮点数,请从地图开始使用浮点数,以便引擎不必花时间玩杂耍。

答案 1 :(得分:2)

感谢@ raina77ow表示必要的纠正。我继续检查代码并将其更改如下:

<?php

class UnitConverter {

    public $vulgar_to_float = ['½' => 0.5];

    public function replaceUnicode( $amount = 0 ){
        $half = $this->vulgar_to_float['½'];
        return ( is_numeric( $amount ) )? $amount : $half;
    }

    public function convertAmount($amount, $from, $to){

        if($from === 'pound' && $to === 'ounce'){
            return $amount * 16;
        } else if($from === 'cup' && $to === 'tablespoon'){
            return $this->replaceUnicode( $amount ) * 16;
        } else {
            throw new Exception('Unable to convert ' . $from . ' to ' . $to);
        }
    }
}


function convertIngredients( $arr = null){
    $unit_names = array_column($arr, 'unit_name');
    foreach($unit_names as $key => $unit){
        if( $unit === 'pound'){
            $arr[$key]['amount'] = (new UnitConverter())->convertAmount($arr[$key]['amount'], $unit, 'ounce');
            $arr[$key]['unit_name'] = 'ounce';
        } else if($unit === 'cup'){
            $arr[$key]['amount'] = (new UnitConverter())->convertAmount($arr[$key]['amount'], $unit, 'tablespoon');
            $arr[$key]['unit_name'] = 'tablespoon';
        } else {
          continue;
        }
    }

    return $arr;
}


function generateBreakfast(){
    $array = [
        0 => array( 'amount' => 1, 'unit_name' => 'cup', 'ingredient_name' => 'almond flour'  ),
        1 => array( 'amount' => '½', 'unit_name' => 'cup', 'ingredient_name' => 'erythritol' ),
        2 => array( 'amount' => 1, 'unit_name' => 'large', 'ingredient_name' => 'egg' )
    ];
    return convertIngredients($array);
}

echo '<pre>';
print_r(generateBreakfast());
echo '</pre>';

请参阅live code

代码中有一个地方需要围绕unicode半符号的引号。此外,我试图消除不必要的冗长。一个代码语句创建一个变量然后返回它,而这个代码返回值。我使用了三元语句,并使用array_column()以更直接的方式精确定位单元名称。

而且,对于我们中间的厨师来说,更直接地显示单位名称和成分后面的数量:)