user602599
user602599

Reputation: 661

PHP multisort on array field containing underscore

I have an array like this:

$data[] = array('ALT_ID' => '202143_N', 'bmi' => 2.5);
$data[] = array('ALT_ID' => '202144_P', 'bmi' => 1.2);
$data[] = array('ALT_ID' => '202145_N', 'bmi' => 6.6);
$data[] = array('ALT_ID' => '202146_P', 'bmi' => 3.6);
$data[] = array('ALT_ID' => '202147_N', 'bmi' => 7.6);
$data[] = array('ALT_ID' => '202148_P', 'bmi' => 8.6);

How to sort on the ALT_ID (N to P) and bmi (low to high) to get an array like this:

array (
array('ALT_ID' => '202143_N', 'bmi' => 2.5),
array('ALT_ID' => '202145_N', 'bmi' => 6.6),
array('ALT_ID' => '202147_N', 'bmi' => 7.6),
array('ALT_ID' => '202144_P', 'bmi' => 1.2),
array('ALT_ID' => '202146_P', 'bmi' => 3.6),
array('ALT_ID' => '202148_P', 'bmi' => 8.6)
)

Here's what I have tried and its not giving the output in the desired format:

Link to the demo: https://eval.in/142639

<?php
$data[] = array('ALT_ID' => '202143_N', 'bmi' => 2.5);
$data[] = array('ALT_ID' => '202144_P', 'bmi' => 1.2);
$data[] = array('ALT_ID' => '202145_N', 'bmi' => 6.6);
$data[] = array('ALT_ID' => '202146_P', 'bmi' => 3.6);
$data[] = array('ALT_ID' => '202147_N', 'bmi' => 7.6);
$data[] = array('ALT_ID' => '202148_P', 'bmi' => 8.6);

foreach ($data as $key => $row) {
    $volume[$key]  = $row['ALT_ID'];
    $bmi[$key] = $row['bmi'];
}

array_multisort($volume, SORT_ASC, SORT_STRING, $bmi, SORT_ASC, $data);

print_r($data);
?>

Thank you.

Upvotes: 0

Views: 76

Answers (2)

Sharanya Dutta
Sharanya Dutta

Reputation: 4021

Using usort() would be easier:

$data = array();
$data[] = array('ALT_ID' => '202143_N', 'bmi' => 2.5);
$data[] = array('ALT_ID' => '202144_P', 'bmi' => 1.2);
$data[] = array('ALT_ID' => '202145_N', 'bmi' => 6.6);
$data[] = array('ALT_ID' => '202146_P', 'bmi' => 3.6);
$data[] = array('ALT_ID' => '202147_N', 'bmi' => 7.6);
$data[] = array('ALT_ID' => '202148_P', 'bmi' => 8.6);

usort($data, function($a, $b){
$x = substr(strrchr($a['ALT_ID'], '_'), 1);
$y = substr(strrchr($b['ALT_ID'], '_'), 1);
if($x == $y) return $a['bmi']-$b['bmi'];
return strcmp($x, $y);
});

print_r($data);

DEMO

Upvotes: 2

FuzzyTree
FuzzyTree

Reputation: 32392

You need to prepend the last character of ALT_ID to your sort key.

<?php

$data[] = array('ALT_ID' => '202143_N', 'bmi' => 2.5);
$data[] = array('ALT_ID' => '202144_P', 'bmi' => 1.2);
$data[] = array('ALT_ID' => '202145_N', 'bmi' => 6.6);
$data[] = array('ALT_ID' => '202146_P', 'bmi' => 3.6);
$data[] = array('ALT_ID' => '202147_N', 'bmi' => 7.6);
$data[] = array('ALT_ID' => '202148_P', 'bmi' => 8.6);

foreach ($data as $key => $row) {
    $pieces = explode('_',$row['ALT_ID']);
    $id_piece = $pieces[1];
    $volume[$key]  = $id_piece . $row['ALT_ID'];
    $edition[$key] = $row['bmi'];
}

//edit
array_multisort($volume, SORT_ASC, $edition, SORT_DESC, $data);

print_r($data);

?>

Upvotes: 1

Related Questions