如何对一组Imperial值(英寸分数)进行排序?

时间:2017-05-09 10:28:25

标签: php arrays sorting fractions

我使用以下代码使用本机排序算法对值进行排序。

usort($this->_items, function($a, $b) { return strnatcasecmp($a['label'], $b['label']);}); 

但问题是它没有为以下内容正确排序值:

$array=array( '18"', '4"', '18 1/2"', '18 1/4"');

应按以下顺序对值进行排序

4"
18"
18 1/4"
18 1/2"

有什么办法可以用PHP代码进行这种排序吗?感谢。

2 个答案:

答案 0 :(得分:0)

这是一个很小的解决方案(Demo):

$array=array('18 1/2"','18"','4"','18 11/12"','18 1/4"');
foreach($array as $k=>$v){
    $copy[$k]=preg_match("/(\d+)\/(\d+)/",$v,$m)?$m[1]/$m[2]+(int)$v:(int)$v;
}
array_multisort($copy,SORT_NUMERIC,$array);
var_export($array);

输出:

array (
  0 => '4"',
  1 => '18"',
  2 => '18 1/4"',
  3 => '18 1/2"',
  4 => '18 11/12"',
)

foreach()迭代$array并在每个值上调用preg_match()以生成$copy数组值。如果它包含尾随分数,那么分数将转换为十进制格式并添加到整数,否则字符串值将转换为整数。

然后array_multisort()使用$copy$array进行排序。完成!

答案 1 :(得分:0)

今天我遇到了一个非常类似的问题,唯一的区别是数字格式略有不同。

5/8

1-3 / 4

2-13 / 54

54/64

还有几百个这种风格我的正则表达式解决方案

preg_match_all("/(^.*?)-?(\d+)\/(\d+)/",$input,$matches)

这个提供的答案的主要优点是第一个捕获组将始终匹配整数,如果您必须提供0 5/8或0-5 / 8的前一个正则表达式,您可以简单地让正则表达式将第一个捕获组留空。之后就像

一样简单
$decimalConversion = $matches[2]/$matches[3]+$matches[1]

如果您对$ matches [0]感到好奇,它将返回所有匹配项。此正则表达式也不能匹配整数,但由于你真的不需要对它们进行任何转换,只要它们保留在数组中,你仍然应该能够正确地进行排序。

此外,我从http://php.net/manual/en/function.array-multisort.php引入array_msort作为更容易阅读和使用array_multisort的替代

之后我使用array_values($ array)将键重置为新排序,并通过直接写入eav_attribute_option表将键作为值的option_id的sort_order传递回magento。