自然地对包含数据单位(GB和TB)的范围值的平面阵列进行排序


Naturally sort a flat array of ranged values including data units (GB and TB)

我有以下来自关联数组的输出值(id=>value):

1GB - 4GB
1TB - 2TB
3TB - 5TB
5GB - 16GB
6TB+
17GB - 32GB
33GB - 63GB
64GB - 120GB
121GB - 200GB
201GB - 300GB
301GB - 500GB
501GB - 1TB

我如何对它进行分组和排序,使它从最小到最大:

所以:

1GB - 4GB
5GB - 16GB
17GB - 32GB
33GB - 63GB
64GB - 120GB
121GB - 200GB
201GB - 300GB
301GB - 500GB
501GB - 1TB
1TB - 2TB
3TB - 5TB
6TB+

发布我的评论作为对后代的回答。。。

当您有无法轻松排序的字符串,并且您正在从数据库表中获取数据时,您可以:

  1. 将名为weight的列添加到数据类型的表中整数

  2. 在权重栏中,根据使用方式使用较高或较低的数字您希望对数据进行排序。

  3. 查询数据时,将ORDER BY weight DESC添加到您的查询中以您想要的方式获取结果

如果数据不是来自表,您可以尝试这样做。

$arr = [
    '8TB' => '8TB',
    '1GB' => '4GB',
     '1TB' => '2TB',
     '3TB' => '5TB',
     '5GB' => '16GB',
     '17GB' => '32GB',
     '33GB' => '63GB',
     '64GB' => '120GB',
    ];
foreach($arr as $key => $val){
    $unit = strtoupper(trim(substr($key, -2)));
    $io[$unit][$key] = $val; 
}
function cmpValue($a, $b){
    return (substr($a, 0, -2) > substr($b, 0, -2)) ? true :false;
}
$sd = array_map(function($ele){
   uksort($ele, 'cmpValue');
   return $ele;
}, $io);

function cmpUnit($a, $b){
    $units = array('B'=>0, 'KB'=>1, 'MB'=>2, 'GB'=>3, 'TB'=>4,    'PB'=>5, 'EB'=>6, 'ZB'=>7, 'YB'=>8);
  return $units[$a] > $units[$b];
}
uksort($sd, 'cmpUnit');
$sordArray =  call_user_func_array('array_merge', $sd);
print_r($sordArray);

虽然一组较大的单位可能需要与与不同单位缩写相关的值的查找图结合使用,但这个问题只涉及GBTB,它们将简单地按字母顺序排序。

为了获得最佳效率,请对输入值执行单个循环,并解析前导数及其尾部单位表达式。字符串的其余部分似乎与精确排序无关。

现在您有了要排序的平面数组,将单位和数字传递到array_multisort()中,然后将原始数组写入第三个参数,使其成为";受影响";大堆

另请参阅一个非常相似的问题的相关答案:PHP:对字节数组进行排序

代码:(演示)

$nums = [];
$units = [];
foreach ($array as $v) {
    [$nums[], $units[]] = sscanf($v, '%d%[A-Z]');
}
array_multisort($units, $nums, $array);
var_export($array);

如果输入为:

$array = [
    'a' => '1GB - 4GB',
    'b' => '1TB - 2TB',
    'c' => '3TB - 5TB',
    'd' => '5GB - 16GB',
    'e' => '6TB+',
    'f' => '17GB - 32GB',
    'g' => '33GB - 63GB',
    'h' => '64GB - 120GB',
    'i' => '121GB - 200GB',
    'j' => '201GB - 300GB',
    'k' => '301GB - 500GB',
    'l' => '501GB - 1TB',
];

输出为:

array (
  'a' => '1GB - 4GB',
  'd' => '5GB - 16GB',
  'f' => '17GB - 32GB',
  'g' => '33GB - 63GB',
  'h' => '64GB - 120GB',
  'i' => '121GB - 200GB',
  'j' => '201GB - 300GB',
  'k' => '301GB - 500GB',
  'l' => '501GB - 1TB',
  'b' => '1TB - 2TB',
  'c' => '3TB - 5TB',
  'e' => '6TB+',
)