Reputation: 259
I'm trying to sort an array numerically but the integers are found in the middle of a value, not on the first character. Here is what my array looks like (using dummy values):
$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
sort($array,1);
Output after foreach:
A25
A30
A40
AB25
AB30
AB40
B25
B30
B40
Expected output:
A25
AB25
B25
A30
AB30
B30
A40
AB40
B40
What would be the best sorting method for this? Really appreciate it, thanks!
Upvotes: 0
Views: 153
Reputation: 99
U can use various kinds of ways to sort arrays in PHP. PHP has some good ways build in to do sorting on arrays. In this case I agree with Mark Baker, however I would recommend a preg_replace
to get the numeric value of your strings.
$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
function cmp($a, $b)
{
$v1 = preg_replace("/[^0-9]/", "", $a);
$v2 = preg_replace("/[^0-9]/", "", $b);
if ($v1 == $v2) {
return 0;
}
return ($v1 < $v2) ? -1 : 1;
}
usort($array, "cmp");
var_dump($array);
Look into the PHP information about sorting arrays, php.net/usort and various others.
Upvotes: 0
Reputation: 5340
Here's a stable sort, the result is: "A25" "B25" "AB25" "A30" "B30" "AB30" "A40" "B40" "AB40" .
function getNum($str)
{
preg_match ( '/(\d+)$/', $str, $match );
return intval ( $match [1] );
}
function stableSort($arr)
{
$newArr = array ();
foreach ( $arr as $idx => $ele )
{
$newArr [] = array (
'idx' => $idx,
'val' => $ele
);
}
usort ( $newArr,
function ($a, $b)
{
$d = getNum ( $a ['val'] ) - getNum ( $b ['val'] );
return $d ? $d : $a ['idx'] - $b ['idx'];
} );
$sortArr = array ();
foreach ( $newArr as $ele )
{
$sortArr [] = $ele ['val'];
}
return $sortArr;
}
var_dump ( stableSort ( $array ) );
Upvotes: 0
Reputation: 1761
You can use user defined function with usort to achieve it
<?php
function mySort($a,$b) {
$numA = '';
$strA = '';
$numB = '';
$strB = '';
for($i=0;$i<strlen($a); $i++) {
if(is_numeric($a[$i])) {
$numA .= (string)$a[$i];
}
else {
$strA .= $a[$i];
}
}
for($i=0;$i<strlen($b); $i++) {
if(is_numeric($b[$i])) {
$numB .= (string)$b[$i];
}
else {
$strB .= $b[$i];
}
}
$numA = (int)$numA;
$numB = (int)$numB;
if($numA>$numB) {
return true;
}
elseif($numA<$numB) {
return false;
}
else {
if(strcmp($strA,$strB)>0) {
return true;
}
else {
return false;
}
}
}
$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
var_dump($array);
usort($array,'mySort');
var_dump($array);
?>
Upvotes: 0
Reputation: 1036
Have created a custom function depending on your requirement, please see below code
<?php
$array = array('A30','A25','ZZZ','A40','Rohan','B25','B30','Sakhale','B40','AB25','AB30','AB40');
$array = sortArrayByNumber($array);
var_dump($array);
/**
* @name sortArrayByNumber
* @abstract sort the entire array irrespective of the string, but the numbers into it
* also we append the elements not having any number at the end
* @author Rohan Sakhale
*/
function sortArrayByNumber($arr){
$sortedArr = array();
$tempArray = array();
$stringOnlyArray = array();
foreach($arr as $v){
$num = getNumberFromString($v);
/**
* If no number found, append it into stringOnlyArray
*/
if($num == ''){
$stringOnlyArray[] = $v;
continue;
}
if(!isset($tempArray[$num])){
$tempArray[$num] = array();
}
$tempArray[$num][] = $v;
}
$tempArrayKeys = array_keys($tempArray);
sort($tempArrayKeys);
foreach($tempArrayKeys as $key){
sort($tempArray[$key]);
$sortedArr = array_merge($sortedArr, $tempArray[$key]);
}
if(count($stringOnlyArray) > 0){
sort($stringOnlyArray);
$sortedArr = array_merge($sortedArr, $stringOnlyArray);
}
return $sortedArr;
}
/**
* @str - String param which tend to have number
*/
function getNumberFromString($str){
$matches = null;
preg_match_all('!\d+!', $str, $matches);
if(!is_null($matches) and is_array($matches)){
if(isset($matches[0][0])){
return $matches[0][0];
}
}
return '';
}
?>
Here sort by number method is trying to firstly identify the number's in your string and maintain a separate array of it based on the keys, later we sort in ascending order every key's of number and then we finally merge it into sorted array
Upvotes: 0
Reputation: 212452
$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
usort(
$array,
function($a, $b) {
list($achar,$anum) = sscanf($a, '%[A-Z]%d');
list($bchar,$bnum) = sscanf($b, '%[A-Z]%d');
if ($anum > $bnum) {
return 1;
} elseif (($anum == $bnum) && ($achar > $bchar)) {
return 1;
}
return -1;
}
);
var_dump($array);
Upvotes: 3