0

I have an array:

Array (
       '9:00',
       '22:00',
       '12:00',
       '*15:00'
)

I'm trying to sort as this way:

Array (
       '9:00',
       '12:00',
       '*15:00',
       '22:00'
)

Is that possible? I'm trying to ignore the asterisk in the array to sort, but the asterisk remains in the element.

5
  • Is the asterisk in front of the 15 a typo? Or is it meant to be there? Are there any other of such characters in the data set? Commented Sep 18, 2014 at 18:37
  • 1
    If you want to keep asterisk, then you probably need to write your own sorting function. So far, there is no built in function to do that. Commented Sep 18, 2014 at 18:38
  • There is no way to sort natively in PHP if you have something like a * preceding. You'll need to make a function to strip leading special chars, use natcasesort (probably the best here) and then reference keys to the original array to get the real value. Commented Sep 18, 2014 at 18:38
  • 1
    usort() with a callback Commented Sep 18, 2014 at 18:40
  • The asterisk always appears in the front of element. Commented Sep 18, 2014 at 18:40

2 Answers 2

2

How about this:

$foo = array('9:00', '22:00', '12:00', '*15:00');

usort($foo, function($a, $b) {
    $a = preg_replace('|[^\d:]|', '', $a);
    $b = preg_replace('|[^\d:]|', '', $b);

    return strnatcmp($a, $b);
});

print_r($foo);

Output:

Array
(
    [0] => 9:00
    [1] => 12:00
    [2] => *15:00
    [3] => 22:00
)
Sign up to request clarification or add additional context in comments.

Comments

0

Logically, your strings will have between 4 and 6 characters. By left padding every string with asterisks to a standard length of 6 characters, you no longer need to perform a natural sort to accommodate missing zeros or asterisks.

Using array_multisort() will offer better performance because the data-mutating step will make n iterated calls of sprintf(), but usort() will call preg_replace() twice and strnatcmp() once n log n times (IOW, it's more expensive).

'*6 means left pad the string (%s) with the * character to ensure that the string has a length of 6 characters.

Code: (Demo)

$array = [
       '12:00',
       '*15:00',
       '9:00',
       '22:00'
];

array_multisort(
    array_map(fn($v) => sprintf("%'*6s", $v), $array),
    $array
);
var_export($array);

Output:

array (
  0 => '9:00',
  1 => '12:00',
  2 => '*15:00',
  3 => '22:00',
)

Of course this will work just the same too if you don't want to make mapped calls of anything: (Demo)

array_multisort(
    str_replace('*', '', $array),
    SORT_NATURAL,
    $array
);
var_export($array);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.