Reputation: 63
I have an array of filenames that I aquire using DirectoryIterator. I am trying to get the filenames to sort so they would be in order like so, this is the way they appear on the server.
2DAYSALEGATE_PG1.jpg 2DAYSALEGATE_PG2.jpg 722_PG1.jpg PW_PG2_COKE_A.jpg PW_PG3_COKE_A.jpg PWBY4_DELI-1.jpg
When aquiring the file names they are coming out like this. I have tried to use a sort, natsort and natcasesort. The filename the underscore character is considered after the letters. What can I do to get the underscore to sorted as a priority character.
array(6) {
[0]=>
string(20) "2DAYSALEGATE_PG1.jpg"
[1]=>
string(20) "2DAYSALEGATE_PG2.jpg"
[2]=>
string(11) "722_PG1.jpg"
[5]=>
string(16) "PWBY4_DELI-1.jpg"
[3]=>
string(17) "PW_PG2_COKE_A.jpg"
[4]=>
string(17) "PW_PG3_COKE_A.jpg"
}
Thanks
Upvotes: 3
Views: 1267
Reputation: 47894
Yes, the fact that the underscore appears in the ascii table in a small section of symbols between uppercase letters and lowercase letters is problematic for your desired natural sort.
To move that DELI string higher in the results, temporarily replace the underscores in every string with a space and use natural sorting. The trouble with using 0 as a replacement character is that when the new zero follows another integer, it is effectively multiplying that integer by 10 -- this creates an unreliable sort.
For best efficiency, call str_replace()
inside of array_multisort()
. This will have a lower time complexity than calling usort()
. (usort()
will need to call str_replace()
twice for at least every element in the array, plus as many times as needed to break ties.)
Code: (Demo)
array_multisort(
str_replace('_', ' ', $array),
SORT_NATURAL,
$array
);
Output:
array (
0 => '2DAYSALEGATE_PG1.jpg',
1 => '2DAYSALEGATE_PG2.jpg',
2 => '722_PG1.jpg',
3 => 'PWBY4_DELI-1.jpg',
4 => 'PW_PG2_COKE_A.jpg',
5 => 'PW_PG3_COKE_A.jpg',
)
Upvotes: 0
Reputation: 8652
You can use the php usort
method, check it out here
with usort
you can implement your custom compare to
function and sort the array according to it.
the custom compare to
function is int callback ( mixed $a, mixed $b )
, you should return a value less than 0 if $a < $b
, zero if equal and a value bigger than 0 when $a > $b
implement your preferred order of sorting using this method
example:
function cmp($a, $b) {
$aTemp = str_replace('_', '0', $a);
$bTemp = str_replace('_', '0', $b);
return strcmp($aTemp,$bTemp);
}
usort($arr, "cmp");
Upvotes: 7
Reputation: 1102
Not sure what you can do here. Lexically, the underscore has a higher ASCII value than any alphanumeric character.
Replacing the underscore with a low ASCII value like \x01, then sorting, then replacing the low ASCII value with an underscore, will give the result you want, but that seems pretty expensive for a trivial change in order.
Upvotes: 3