Home > Mobile >  Sort array of weight measurements with different gram units
Sort array of weight measurements with different gram units

Time:05-03

Example Input:

$weights = ['1 Kg','300 g','1.5 Kg','20 g','5 Kg'];

Output should be

$sorted_weights = ['20 g','300 g','1 Kg','1.5 Kg','5 Kg'];

CodePudding user response:

Please use the below code and let me know if it helps or not:

$weights = ['1 Kg','300 g','1.5 Kg','20 g','5 Kg'];

$r = [];

foreach ($weights as $v) {

    if (strpos($v, 'g') !== false) {$k = 1;} // 1 g
    if (strpos($v, 'Kg') !== false) {$k = 1000;} // 1 kilogram = 1000 g

    $r[floatval($v)*$k] = $v;
}
ksort($r);//ksort used to sort array by key
print_r($r);

CodePudding user response:

usort is the appropriate function to sort arrays with values that need to be evaluated or converted against each other. The following example assumes that only values with g or kg are available.

$weights = ['1 Kg','300 g','1.5 Kg','20 g','5 Kg', '1000 g'];

usort($weights, function($a,$b){
  $a = stripos($a,'k') ? 1000 * floatval($a) : floatval($a);
  $b = stripos($b,'k') ? 1000 * floatval($b) : floatval($b);
  return $a <=> $b;
});

/*
array (
  0 => "20 g",
  1 => "300 g",
  2 => "1 Kg",
  3 => "1000 g",
  4 => "1.5 Kg",
  5 => "5 Kg",
)
*/

CodePudding user response:

  1. Parse each string in a loop, translate the unit into its factor value, multiply, and push into a new array.
  2. Sort the original array using the new array.

The approach below will not break when duplicate amounts are found because keys are not used. Also, from PHP8.1, using float values as keys are deprecated prior to that, floats used as keys are truncated to integers which may yield unpredictable results.

Using usort() is not a good choice for this task because the function will perform redundant function calls while re-visiting elements to break ties. The way to avoid unnecessary function calls is to loop through the input array just once and store the calculations in a separate array like below.

Code: (Demo)

const UNIT_FACTOR = [
    'g' => 1,
    'Kg' => 1000,
];

$weights = ['1 Kg','300 g','1.5 Kg','20 g','5 Kg'];

foreach ($weights as $weight) {
    sscanf($weight, '%f %s', $amount, $unit);
    $grams[] = $amount * UNIT_FACTOR[$unit];
}

array_multisort($grams, $weights);
var_export($weights);

Output:

array (
  0 => '20 g',
  1 => '300 g',
  2 => '1 Kg',
  3 => '1.5 Kg',
  4 => '5 Kg',
)
  • Related