如何优化这些大量的 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 ? ' $' : '';
?>
$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";
打破逻辑。
你有一个
$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或美元价值是如何确定的,我可能会想出更清楚的东西,但我认为这已经比其他答案领先一英里了随着清晰度/可读性/可维护性的发展。
如果您使用的是 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
,以此类推)