For some reason I keep getting this notice when I try to loop through an array and change it's values.
For some reason, the array is passing 2 values, the one before and the one after when running the same function that changes the values.
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>';
So in the convertIngredients, we're calling the convertAmount method, but for some reason there.. it's passing this '1½' instead of just calling the method individually with each iteration.
If you take a look here: https://eval.in/944452 , the amount in erythritol is showing 16, but it should be 8 because 1/2 of 16 = 8.
Replace vulgar_to_float
with...
public $vulgar_to_float = array('½' => 0.5);
... and it should work.
As it stands, 16 * '1/2'
expression is evaluated by the code. You probably hope that PHP automatically 'resolves' the second operand to a correct numeric value. But it doesn't, as the parsing rules (applied to a string in attempt to cast it to a number) don't treat '/'
character in any special way - hence it's discarded, along with the rest of string.
That means, value of 16 * '1/2'
is essentially equal to 16 * 1
- which is, as you clearly noticed, 16.
The change prevents this error - and makes life for PHP a little bit easier: if you're going to get a float as replaceUnicode
return value, use floats in your map right from the start so that the engine won't have to spend time on type juggling.
Kudos to @raina77ow for indicating the necessary correction. I went ahead and reviewed the code and altered it as follows:
<?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>';
See live code
There was a place in the code that needed quotes around the unicode one-half symbol. Also, I tried to eliminate unnecessary verbosity. One code statement creates a variable and then returns it whereas this code returns the value. I used a ternary statement and I used array_column() to pinpoint the unit names in a more straightforward fashion.
And, for the cooks among us, more straightforward to show the unit name and the amount followed by the ingredient :)