【问题标题】:Elegant way to get minimum between two prices while throwing out non-positive values在抛出非正值的同时获得两个价格之间的最小值的优雅方式
【发布时间】:2018-09-03 11:45:42
【问题描述】:

目前,我正在分几步执行此操作,不知道是否有更好的方法。

这就是我的做法。

  1. 检查这些值是非数字还是非正数。如果是,则抛出错误并退出。这保证了至少 1 个正数。
  2. 将两个值都转换为(float)。如果两者之一是非数字,现在应该是 0。
  3. 如果 num1 为零,则使用 num2。否则,如果 num2 为零,则使用 num1。否则使用min(num1,num2)

// 1
if(!(is_numeric($num1) && $num1 >0) && !(is_numeric($num2) && $num2 >0) ) {
    die('error');
}
// at least one is a positive number. Other could be a different number or not numeric.

// 2
$num1 = (float)$num1;
$num2 = (float)$num2;
// now both are numbers, at least one is positive

// 3
if($num1 <= 0) {
    $price = $num2;
} elseif($num2 <= 0) {
    $price = $num1;
} else {
    $price = min($num1,$num2);
}
// finally we have the price

我正在使用 php5

【问题讨论】:

  • 你的代码块没有像你预期的那样格式化,因为列表项格式化了它。我添加了--- 来创建水平线和break 列表格式。否则,您可以在每行代码中再添加 4 个空格,但这会将您的 sn-p 嵌套在第三个列表项中。

标签: php validation floating-point minimum


【解决方案1】:

我建议您将数字转换为浮点数,然后再将它们与0 进行比较;这将强制非数字为0,然后您可以一步过滤掉负数、原始零和转换后的零。如果没有符合条件的价格,请提前退货。如果存在至少一个符合条件的价格,则返回两者中较低的一个。

为了方便、简化、DRY 编程,我将值批处理到一个数组中以便快速处理。

代码:(Demo)

function newGetMinPrice($nums) {
    $nums = array_filter($nums, function($v){ return (float)$v > 0;});  // convert to float and check if greater than 0
    if (empty($nums)) {
        return 'error';  // if no qualifying prices, return error
    }
    return min($nums);  // return the lowest qualifying price
}

$tests = [[0, .1], [1, 'foo'], [.24, -.25], [3, 3], ['foo', 'bar'], [-0, 0.1], [90, -90], [0, 0], [1, 1]];
foreach ($tests as $test) {
    echo "new: {$test[0]} -vs- {$test[1]} = ",newGetMinPrice($test), "\n";
}

输出:(与您发布的 sn-p 相同的性能

new: 0 -vs- 0.1 = 0.1
new: 1 -vs- foo = 1
new: 0.24 -vs- -0.25 = 0.24
new: 3 -vs- 3 = 3
new: foo -vs- bar = error
new: 0 -vs- 0.1 = 0.1
new: 90 -vs- -90 = 90
new: 0 -vs- 0 = error
new: 1 -vs- 1 = 1

...或者你可以像这样浓缩:

$nums = array_filter($nums, function($v){ return (float)$v > 0;});  // convert to float and check if greater than 0
return empty($nums) ? 'error' : min($nums);

附言如果您不想使用array_filter(),您也可以生成一系列条件...尽管我认为它并不比您原来的 sn-p 更漂亮。

$num1 = max(0, (float)$num1);
$num2 = max(0, (float)$num2);
if ($num1 === 0) {                    // bad num1
    if ($num2 === 0) {                // bad num2
        return 'error';              // send error
    }
    return $num2;                    // send good num2
}
// 1 is good...
if ($num2 === 0 || $num1 <= $num2) {  // bad num2 or num1 better than num2
    return $num1;                    // send good/better num1
}
return $num2;                        // both num1 and num2 are good, send num2

或者不声明newGetMinPrice():

$nums = array((float)$num1,(float)$num2);  // force input values to float values
$nums = array_filter($nums, function($v){return $v > 0;});  // check if greater than 0
if (empty($nums)) {
    die('error');
} else {
    $price = min($nums);  // declare lowest qualifying price
}

Demo

【讨论】:

  • @Buttle 如果您有任何我的解决方案无法正确处理的边缘情况,请提供输入数据,我会调整答案。
  • @Buttle 你运行的是哪个 php5 版本?我想这将决定我是否在我的解决方案/演示中使用了任何过于现代的组件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多