特定数字介于其他数字之间时的优化

问题描述 投票:0回答:3

如何优化这些大量的 if? Co2 付款从 131 开始到 301 结束,所以直到 131 为 0 并且超过 301 与 301 相同。尝试使用

array
但不知道如何从数组中获取价格,如果数字对应于 co2 plus需要知道 fuel_id。无法想象这段代码应该如何看待
switch()
.

<?php
$co2 = '170'; // co2 number taking from DB

// fuel id taking from DB
(1, 'Petrol'),
(2, 'Diesel'),
(3, 'Electic'),
(4, 'Petrol / Gas'),
(5, 'Petrol / Hibrid'),
(6, 'Diesel / Hibrid'),
(7, 'Petrol / Hibrid / Plug-in'),
(8, 'Petrol / Hibrid / Gas'),
(9, 'Diesel / Hibrid / Plug-in');

echo $co2 ? 'Your co2 price is ' : '';

// Payment going from 131 co2
if($co2 >= 131 && $co2 <= 140){
    echo $fuel_id == 2 ? '40.47' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '20.24';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '18.21';}
}else if($co2 >= 141 && $co2 <= 150){
    echo $fuel_id == 2 ? '80.94' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '40.47';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '36.42';}
}else if($co2 >= 151 && $co2 <= 160){
    echo $fuel_id == 2 ? '121.41' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '60.71';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '54.63';}
}else if($co2 >= 161 && $co2 <= 170){
    echo $fuel_id == 2 ? '161.88' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '80.94';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '72.85';}
}else if($co2 >= 171 && $co2 <= 180){
    echo $fuel_id == 2 ? '202.35' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '101.18';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '91.06';}
}else if($co2 >= 181 && $co2 <= 190){
    echo $fuel_id == 2 ? '242.82' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '121.41';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '109.27';}
}else if($co2 >= 191 && $co2 <= 200){
    echo $fuel_id == 2 ? '283.29' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '141.65';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '127.48';}
}else if($co2 >= 201 && $co2 <= 210){
    echo $fuel_id == 2 ? '323.76' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '161.88';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '145.69';}
}else if($co2 >= 211 && $co2 <= 220){
    echo $fuel_id == 2 ? '364.23' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '182.12';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '163.9';}
}else if($co2 >= 221 && $co2 <= 230){
    echo $fuel_id == 2 ? '404.7' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '202.35';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '182.12';}
}else if($co2 >= 231 && $co2 <= 240){
    echo $fuel_id == 2 ? '445.17' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '222.59';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '200.33';}
}else if($co2 >= 241 && $co2 <= 250){
    echo $fuel_id == 2 ? '485.64' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '242.82';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '218.54';}
}else if($co2 >= 251 && $co2 <= 260){
    echo $fuel_id == 2 ? '526.11' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '263.06';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '236.75';}
}else if($co2 >= 261 && $co2 <= 270){
    echo $fuel_id == 2 ? '566.58' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '283.29';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '254.96';}
}else if($co2 >= 271 && $co2 <= 280){
    echo $fuel_id == 2 ? '607.05' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '303.53';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '273.17';}
}else if($co2 >= 281 && $co2 <= 290){
    echo $fuel_id == 2 ? '647.52' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '323.76';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '291.38';}
}else if($co2 >= 291 && $co2 <= 300){
    echo $fuel_id == 2 ? '687.99' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '344';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '309.6';}
}else if($co2 >= 301){
    echo $fuel_id == 2 ? '728.46' : '';
    if($fuel_id == 1 || $fuel_id == 5 || $fuel_id == 7  || $fuel_id == 8) {echo '364.23';}
    if($fuel_id == 4 || $fuel_id == 8) {echo '327.81';}
}

echo $co2 ? ' $' : '';
?>
php refactoring
3个回答
0
投票
$co2 = '170';
$fuel_id = 1;

$type = match ( $fuel_id ) {
  2          => 't2',
  1, 5, 7, 8 => 't1578',
  4, 9       => 't49',
  default    => ''
};

$result = match ( true ) {
  $co2 >= 131 && $co2 <= 140 => [ 't2' => '40.47', 't1578' => '20.24', 't49' => '18.21' ],
  $co2 >= 141 && $co2 <= 150 => [ 't2' => '80.94', 't1578' => '40.47', 't49' => '36.42' ],
  $co2 >= 151 && $co2 <= 160 => [ 't2' => '121.41', 't1578' => '60.71', 't49' => '54.63' ],
  $co2 >= 161 && $co2 <= 170 => [ 't2' => '161.88', 't1578' => '80.94', 't49' => '72.85' ],
  // ...
  $co2 >= 301                => [ 't2' => '728.46', 't1578' => '364.23', 't49' => '327.81' ],
  default                    => [ 't2' => '', 't1578' => '', 't49' => '' ]
};

echo $result[$type] ?: 'no match';

所以数据的结构好像是这样的:

每个范围(131 - 140、141 - 150 等)都有 $fuel_id 的值,它们是第一个条目(范围 131 - 140 的值)的倍数。

所以基本上可以从 $co2 中减去 130,将它除以每个范围的长度 (10),计算结果,这给出了范围为 131 - 140 的第一个条目中这些“起始”值的乘数。

请注意,与 OP 中的数据相比,结果将略有偏差(仅对于某些条目而言为 0,01 到 0,0x)。

$co2 = random_int(131, 400);
$fuel_id = random_int(1, 9);

$start = [
  1 => 20.24,
  2 => 40.47,
  3 => 0,       // no value for $fuel_id = 3 in the OP
  4 => 18.21,
  5 => 20.24,
  6 => 0,       // no value for $fuel_id = 6 in the OP
  7 => 20.24,
  8 => 20.24,   // or 18.21 ( 8 is used in two places
  9 => 18.21    // or 20.24   in the code of the OP )
];

$result = $start[$fuel_id] * ceil(( $co2 - 130 ) / 10);

echo "co2: $co2 & fuel_id: $fuel_id -> $result";

0
投票

打破逻辑。

你有一个

$co2
值,和一个严格的类型地图,实际上只有 3 个类别重复得令人作呕。

class CO2MapThing {

    public function __construct(protected array $map) {}

    protected function mapType(int $type) {
        // FYI: your code has no 3/6/9, and 8 is listed twice, but this is how your code shakes out.
        switch($type) {
            case 2: return 0;
            case 1:
            case 5:
            case 7:
            case 8: return 1;
            case 4: return 2;
            default:
                throw new \Exception("Unknown type: $type");
        }
    }

    public function getCost(int $co2, int $type) {
        foreach( $this->map as $key => $value) {
            if( $key > $co2 ) {
                return $this->map[$key][$this->mapType($type)];
            }
        }
    }
}

$map = [
    120 => [   '0.00',   '0.00',   '0.00' ],
    130 => [  '40.47',  '20.24',  '18.21' ],
    140 => [  '80.94',  '40.47',  '36.42' ],
    150 => [ '121.41',  '60.71',  '54.63' ],
    // ...
    PHP_INT_MAX =>
           [ '728.46', '364.23', '327.81' ]
];

$m = new CO2MapThing($map);

var_dump(
    $m->getCost(110,1),
    $m->getCost(120,1),
    $m->getCost(130,1),
    $m->getCost(990,1)
);

输出:

string(4) "0.00"
string(5) "20.24"
string(5) "40.47"
string(6) "364.23"

如果我真的知道这些价值中的任何一个实际上meant或美元价值是如何确定的,我可能会想出更清楚的东西,但我认为这已经比其他答案领先一英里了随着清晰度/可读性/可维护性的发展。


-2
投票

如果您使用的是 PHP 版本 8 或更高版本,则可以使代码更紧凑并可能更快

match
:

echo match (true) {
    ($co2 < 131) => '',

    ($co2 <= 140) => 
        match ($fuel_id) {
            2 => '40.47',
            1, 5, 7, 8 => '20.24',
            4 => '18.21',
            default => '',
        },
    ($co2 <= 150) => 
        match ($fuel_id) {
            2 => '80.94',
            1, 5, 7, 8 => '40.47',
            4 => '36.42',
            default => '',
        },
    // etc for other boundary points on $co2
     
    default => '',
};

顶层

match
中的条件是按顺序计算的,所以不需要继续检查下界(即如果它没有匹配
$co2 <= 140
那么我们已经知道
$co2
大于140当我们来评估下一个条件
$co2 <= 150
,以此类推)

© www.soinside.com 2019 - 2024. All rights reserved.