skip to Main Content

I did this

while....//to get dynamic value of $data[18]
One of the value is
$data[18] = '256000000000;2001111162880;2001111162880;2001111162880;10000831348736;1800360124416;256000000000';

$result = [];
foreach(explode("n", $data[18]) as $str){
$result[] = implode("GB/", array_map(fn($v) => floor((int)$v / 1e9), explode(";", $str))). 'GB';
}
$data[18] = implode("n", $result); //GB

$tb = ((int)substr($data[18],0,-2) / 1000);
$data[18] = preg_replace('~bw{6,}b~', $tb . 'TB', $data[18]); //TB

echo $data[18];

And gets

256GB/0.256TB/0.256TB/0.256TB/0.256TB/0.256TB/256GB

What I expected was (I know my code was wrong to begin with)

256GB/2TB/2TB/2TB/10TB/1.8TB/256GB

However, the final result that I actually want is (the order doesn’t matter)

2 x 256GB/3 x 2TB/10TB/1.8TB

Sometimes value of $data[18] is empty or only 1. eg. $data[18] = '1800360124416';
In that case I want an empty result or just 1.8TB (without 1 x )

2

Answers


  1. function formatBytes(string $bytes): string {
      if ($bytes === '') return '';
      $factor = (int)floor(( strlen($bytes) - 1 ) / 3);
      return str_replace('.0', '', round($bytes / 1024 ** $factor, 1)) . [ 'B', 'KB', 'MB', 'GB', 'TB' ][$factor];
    }
    
    $input = '256000000000;2001111162880;2001111162880;2001111162880;10000831348736;1800360124416;256000000000';
    
    $values = explode(';', $input);
    
    rsort($values);
    
    $grouped = [];
    foreach ($values as $bytes) {
      $grouped[$bytes] = array_key_exists($bytes, $grouped) ? $grouped[$bytes] + 1 : 1;
    }
    
    $formatteds = [];
    foreach ($grouped as $bytes => $count) {
      $formatteds[] = ( $count === 1 ? '' : $count . 'x' ) . formatBytes($bytes);
    }
    
    $result = implode('/', $formatteds);
    
    echo $result;   // Output: 9.1TB/3x1.8TB/1.6TB/2x238.4GB
    
    Login or Signup to reply.
  2. I think using something like this is a better way to aggregate the data:

    <?php
    $data[18] = '256000000000;2001111162880;2001111162880;2001111162880;10000831348736;1800360124416;256000000000';
    $array = str_getcsv($data[18], ';');
    // or $array = preg_split('/[n;]/', $data[18], -1, PREG_SPLIT_NO_EMPTY); if new lines and semi-colons are delimiter
    foreach(array_count_values($array) as $value => $thedata){
         echo $value . ($thedata > 1 ? ' x ' . $thedata: '') . PHP_EOL;
    }
    

    There a many human readable functions to convert bytes to a human readable format. It’s not clear to me how you want the data converted though. From above example passing $value to any of those functions should achieve your goal.

    https://3v4l.org/iQrC5

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search