1

I write an array like this:

$tags = [
    "Channel1\n" . 26210,
    "Channel2\n" . 7896 . "\n---------------",
    "Channel3\n" . 5035 . "\n---------------",
    "Channel4\n" . 25794 . "\n---------------",
    "Channel5\n" . 91143 . "\n---------------",
    "Channel6\n" . 42075 . "\n---------------",
    "Channel7\n" . 11815 . "\n---------------",
    "Channel8\n" . 180 . "\n---------------",
    "Channel9\n" . 171 . "\n---------------",
    "Channel10\n" . 82106  . "\n---------------"
];

Now I use sort() function to sort this array, But I need it sorted only by those integers that display between two strings (specific part of an array). For example: Channel9 - 171 , Channel8 - 180 ...

6
  • 1
    You need to state how you get the array, do you define it like that or get it from somewhere? Also, show what output you want to get. Commented Feb 8, 2017 at 15:48
  • 1
    So what is your problem? You can't sort? You can't show? You can't what? Commented Feb 8, 2017 at 15:48
  • @AbraCadaver i wanna get the correct order of those integer with own concatenates. for example : Channel9 - 171 | Channel8 - 180 and ... Commented Feb 8, 2017 at 15:53
  • You should be use uasort() to define sort rules by yourself. Commented Feb 8, 2017 at 15:55
  • @CalosKao please give me an example, im new to PHP Commented Feb 8, 2017 at 15:59

2 Answers 2

1

I would probably get the numbers in an array and sort on that:

$nums = preg_filter('/[^\n][^\d]+/', '', $tags); //or preg_replace()
array_multisort($nums, $tags);

A slightly longer approach:

usort($tags, function($a, $b) {
                 $a = explode("\n", $a)[1];
                 $b = explode("\n", $b)[1];
                 if ($a == $b) { return 0; }
                 return ($a < $b) ? -1 : 1;
             });
Sign up to request clarification or add additional context in comments.

Comments

0
  1. preg_filter() offers no advantage over preg_replace(). preg_filter() (in fringe cases not represented in the asker's sample data) can mutate the size of the array which would lead to code breakage when implemented with array_multisort() because the sorting atray's size must be the same as the input array.
  2. /[^\n][^\d]+/ actually damages all elements except the first element.

Instead, I recommend preparing the sorting array with preg_replace() and a whole-string pattern with a capture group.

The generated array of numeric strings will be treated as integers by default in the array_multisort().

Code: (Demo)

array_multisort(
    preg_replace(
        "/\S+\n(\d+).*/s",
        '$1',
        $tags
    ),
    $tags
);
var_export($tags);

The regex pattern matches non-whitespace characters, then a newline, then captures the full integer value, then greedily matches the rest of the string. The captured numeric string is then used to replace the whole input string. The same behavior is applied to all elements in the array.


Using usort() is less attractive because it would require two function calls per iteration. In other words, just use array_multisort() for best efficiency / fewer function calls.

Below sscanf() is used to parse the predictably formatted string. %*[^\n] will match (but not return) the leading substring upto the first \n, then match and return the second numeric substring as an int-type value.

Code: (Demo)

usort(
    $tags,
    fn($a, $b) =>
        sscanf($a, "%*[^\n]%d")
        <=>
        sscanf($b, "%*[^\n]%d")
);
var_export($tags);

Or trim all characters prior to the first occurring newline, then cast that string to an integer to remove the unwanted characters. (Demo)

usort(
    $tags,
    fn($a, $b) =>
        (int) strpbrk($a, "\n")
        <=>
        (int) strpbrk($b, "\n")
);
var_export($tags);

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.