-2

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'];
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • I catered [my new necropost](https://stackoverflow.com/a/72098152/2943403) to also handle your scenario. – mickmackusa May 03 '22 at 10:34
  • In the future, please only post questions with proof of research and an attempt to self-resolve. This should help you to avoid asking a duplicate question and avoid receiving downvotes. – mickmackusa May 03 '22 at 23:00

2 Answers2

0

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);
Sachin
  • 397
  • 4
  • 13
  • 1
    The solution only works if all the values of the array are different. With an array like $weights = ['1 Kg','300 g','1.5 Kg','20 g','5 Kg', '1000 g']; then the value 1kg is missing. – jspit May 03 '22 at 07:05
  • 1
    `strpos($v, 'g') !== false` is not an informative check for this task because ALL value contain `g`. Using floats as keys will either give `Deprecated` warnings or truncate values (depending on the PHP version) which is either not pretty or unstable. Relying on keys also leave the script vulnerable to data damage when multiple keys collide. I do not endorse this answer because it is too unsafe. – mickmackusa May 03 '22 at 08:11
0

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",
)
*/
jspit
  • 7,276
  • 1
  • 9
  • 17
  • This technique is calling `floatval()` too many times per iteration. I can be lightened slightly with [`$a = (stripos($a, 'k') ? 1000 : 1) * (float) $a;`](https://3v4l.org/8LcBQ). However, as I explain in my new answer on the duplicate page, `usort()` will be doing redundant function calls while breaking ties. The way to avoid these revisited calculations is to do the calculations just once in a loop, then leveraging that array when sorting. – mickmackusa May 03 '22 at 22:37
  • Very nice @mickmackusa. Since PHP 7, I've completely done without micro-optimizations because PHP does this excellently itself. The array_multisort solution is indeed faster but uses more memory. Relevant effects only become noticeable with very large arrays. – jspit May 04 '22 at 12:11
  • Fair enough. No argument from me. – mickmackusa May 04 '22 at 12:17