Php Sort Array By Number In Filename
Solution 1:
None of the earlier answers are using the most appropriate/modern technique to perform the 3-way comparison -- the spaceship operator (<=>
).
Not only does it provide a tidier syntax, it also allows you to implement multiple sorting rules in a single step.
The following snippet break each filename string in half (on the underscore), then compare the 2nd half of both filenames first, and if there is a tie on the 2nd halves then it will compare the 1st half of the two filenames.
Code: (Demo)
$photos = [
'photo-Bname_0333.jpg',
'photo-Bname_0222.jpg',
'photo-Aname_0333.jpg',
'photo-Cname_0111.jpg',
'photo-Cname_0222.jpg',
'photo-Aname_0112.jpg',
];
usort($photos, function ($a, $b) {
return array_reverse(explode('_', $a, 2)) <=> array_reverse(explode('_', $b, 2));
});
var_export($photos);
Output:
array (
0 => 'photo-Cname_0111.jpg',
1 => 'photo-Aname_0112.jpg',
2 => 'photo-Bname_0222.jpg',
3 => 'photo-Cname_0222.jpg',
4 => 'photo-Aname_0333.jpg',
5 => 'photo-Bname_0333.jpg',
)
For anyone who still thinks the preg_
calls are better, I will explain that my snippet is making potentially two comparisons and the preg_
solutions are only making one.
If you wish to only use one sorting criteria, then this non-regex technique will outperform regex:
usort($photos, function ($a, $b) {
return strstr($a, '_') <=> strstr($b, '_');
});
I super-love regex, but I know only to use it when non-regex techniques fail to provide a valuable advantage.
Solution 2:
usort is a php function to sort array using values. usort needs a callback function that receives 2 values.
In the callback, depending of your needs, you will be return the result of the comparision 1, 0 or -1. For example to sort the array asc, I return -1 when the firts value of the callback is less than second value.
In this particular case I obtain the numbers of the filename, and compare it as string, is not necesary to cast as integer.
<?php$photos=[
'photo-Bname_0222.jpg',
'photo-Aname_0333.jpg',
'photo-Cname_0111.jpg',
];
usort($photos, function ($a, $b) {
preg_match("/(\d+(?:-\d+)*)/", $a, $matches);
$firstimage = $matches[1];
preg_match("/(\d+(?:-\d+)*)/", $b, $matches);
$lastimage = $matches[1];
if ($firstimage == $lastimage) {
return0;
}
return ($firstimage < $lastimage) ? -1 : 1;
});
print_r($photos);
Solution 3:
It sorts alphabetically because you use sort() on the filename. The 2nd part of your code does nothing.
You might want to take a look at usort http://php.net/manual/en/function.usort.php You can do something like
functioncmp($a, $b) {
if ($a == $b) {
return0;
}
preg_match('/(\d+)\.\w+$/', $a, $matches);
$nrA = $matches[1];
preg_match('/(\d+)\.\w+$/', $b, $matches);
$nrB = $matches[1];
return ($nrA < $nrB) ? -1 : 1;
}
usort($files_thumb, 'cmp');
Also, I'm not sure about your regex, consider a file named "abc1234cde2345xx". The one I used takes the last digits before a file extension at the end. But it all depends on your filenames.
Solution 4:
sort(array,sortingtype) , you have to set the second parameter of the sort() function to 1 so it will sort items numerically
//calculate andsort
$totaal = 0;
if($handle_thumbs = opendir('thumbs')){
$files_thumbs = array();
while(false !== ($file = readdir($handle_thumbs))){
if($file != "." && $file != ".."){
$files_thumbs[] = $file;
$totaal++;
}
}
closedir($handle_thumbs);
}
sort($files_thumbs,1);
//reset array list
$first = reset($files_thumbs);
$last = end($files_thumbs);
//match andsplit filenames from array values - image numbers
preg_match("/(\d+(?:-\d+)*)/", "$first", $matches);
$firstimage = $matches[1];
preg_match("/(\d+(?:-\d+)*)/", "$last", $matches);
$lastimage = $matches[1];
Post a Comment for "Php Sort Array By Number In Filename"