Search code examples
phparraysmergeconditional-statementstoggle

Merging two arrays by conditionally toggling which array's row should be used next


I've got two arrays with the same objects. They are of the form:

$arrayA = [
    ["sentence" => "Hello world",        "nextSpeaker" => 0],
    ["sentence" => "Hello world again",  "nextSpeaker" => 1],
    ["sentence" => "Hello world twice!", "nextSpeaker" => 1],
];

$arrayB = [
    ["sentence" => "Bye world",       "nextSpeaker" => 1],
    ["sentence" => "Bye world again", "nextSpeaker" => 0],
    ["sentence" => "Bye world twice", "nextSpeaker" => 0],
];

The effect that I want to achieve is, starting with Array A, to merge both arrays but have then in the correct order. So, if from array A, the nextSpeaker is 0, it should take the next result from ArrayA. If the nextSpeaker is 1, then it should take from ArrayB and then look at the next item from ArrayB to see if the next speaker is speaker 1. If not, it shuold look at ArrayA again.

I have tried to just merge both arrays, loop through the merged array and keeping track of the current key for the speaker0 and speaker1 arrays, but I can't really wrap my head around it.

Desired output:

[
    ['sentence' => 'Hello world',        'nextSpeaker' => 0],
    ['sentence' => 'Hello world again',  'nextSpeaker' => 1],
    ['sentence' => 'Bye world',          'nextSpeaker' => 1],
    ['sentence' => 'Hello world twice!', 'nextSpeaker' => 1],
    ['sentence' => 'Bye world again',    'nextSpeaker' => 0],
    ['sentence' => 'Bye world twice',    'nextSpeaker' => 0],
]

Solution

  • This can be done by using a while loop until both arrays are empty. Foreach over the first array with shifting first value off as long as the break condition matches, do the same for the seconds array.

    Warning! This mutates and clears $arrayA and $arrayB. If you don't want it, make a copy first.

    $arrayA = [
        ["sentence" => "Hello world", "nextSpeaker" => 0],
        ["sentence" => "Hello world again", "nextSpeaker" => 1],
        ["sentence" => "Hello world twice!", "nextSpeaker" => 1],
    ];
    
    $arrayB = [
        ["sentence" => "Bye world", "nextSpeaker" => 1],
        ["sentence" => "Bye world again", "nextSpeaker" => 0],
        ["sentence" => "Bye world twice", "nextSpeaker" => 0],
    ];
    
    $arrayC = [];
    
    while ($arrayA || $arrayB) {
        foreach ($arrayA as $array) {
            $arrayC[] = array_shift($arrayA);
            if ($array['nextSpeaker'] == 1) {
                break;
            }
        }
    
        foreach ($arrayB as $array) {
            $arrayC[] = array_shift($arrayB);
            if ($array['nextSpeaker'] == 1) {
                break;
            }
        }
    }
    
    

    results in

    [
        ['sentence' => 'Hello world',        'nextSpeaker' => 0],
        ['sentence' => 'Hello world again',  'nextSpeaker' => 1],
        ['sentence' => 'Bye world',          'nextSpeaker' => 1],
        ['sentence' => 'Hello world twice!', 'nextSpeaker' => 1],
        ['sentence' => 'Bye world again',    'nextSpeaker' => 0],
        ['sentence' => 'Bye world twice',    'nextSpeaker' => 0],
    ]