Search code examples
phparraysalgorithmsortinggrouping

Sort values in ascending groups representing every third value


I have an array that I'd like to reorder by every 3rd item. So it's 1st, 4th, 7th and then 2nd, 5th, 8th and 3rd, 6th, 9th.

Input:

$items = ['1','2','3','4','5','6','7','8','9'];

Desired result:

['1','4','7','2','5','8','3','6','9']

Or it can be 3 separate arrays as well. Like this:

['1', '4', '7']
['2', '5', '8']
['3', '6', '9']

I tried array_chunk($items, count($items) / 3) but it just returns the same array divided into 3 equal arrays.

['1', '2', '3']
['4', '5', '6']
['7', '8', '9']

I don't know if I should use array_chunk and then something else to achieve what I want.

UPDATE: It does not have to be exactly 9 items in the input array. it can be shorter or longer, the key point is that it has to take every 3rd item as long as it finds any and so on...

So if there are 10 items:

$items = ['1','2','3','4','5','6','7','8','9','10'];

Desired result:

['1','4','7','10','2','5','8','3','6','9']

Solution

  • The simplest way I can think of is to loop over the list three times:

    • Start at element 0, skipping by 3, stop when past end of list
    • Start at element 1, skipping by 3, stop when past end of list
    • Start at element 2, skipping by 3, stop when past end of list

    That can be easily achieved using C-style for loop syntax:

    $maxKey = count($items) - 1;
    $rearrangedItems = [];
    for ( $key=0; $key<=$maxKey; $key+=3 ) {
        $rearrangedItems[] = $items[$key];
    }
    for ( $key=1; $key<=$maxKey; $key+=3 ) {
        $rearrangedItems[] = $items[$key];
    }
    for ( $key=2; $key<=$maxKey; $key+=3 ) {
        $rearrangedItems[] = $items[$key];
    }
    

    If you needed to generalize to different offsets, you could put the whole thing into an outer loop rather than copying and pasting:

    $offset = 3;
    $maxKey = count($items) - 1;
    $rearrangedItems = [];
    for ( $start=0; $start<$offset; $start++ ) {
        for ( $key=$start; $key<=$maxKey; $key+=$offset ) {
            $rearrangedItems[] = $items[$key];
        }
    }