在抛出非正值的同时获得两个价格之间的最小值的优雅方式

Posted

技术标签:

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

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

这就是我的做法。

    检查这些值是非数字还是非正数。如果是,则抛出错误并退出。这保证了至少 1 个正数。 将两个值都转换为(float)。如果两者之一是非数字,现在应该是 0。 如果 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 嵌套在第三个列表项中。 【参考方案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 版本?我想这将决定我是否在我的解决方案/演示中使用了任何过于现代的组件。

以上是关于在抛出非正值的同时获得两个价格之间的最小值的优雅方式的主要内容,如果未能解决你的问题,请参考以下文章

如何获得表中所有正值的最小值?

在抛出std :: exception的实例后终止调用

为啥我应该在抛出异常指针时使用按引用捕获

在抛出 'std::length_error' 的实例后调用终止

重新抛出非 MySQL 错误 Node.js

Laravel Blade If 语句在使用 Guard 进行身份验证检查时抛出非对象属性错误