Home > database >  Grouping matching pairs within an array using PHP
Grouping matching pairs within an array using PHP

Time:10-06

Currently, i am trying to group matching pairs, e.g. if its a and b in a row, it should become one item.

My attempt returns:

['a', 'b', 'a', 'b', 'a']
        $test = [
            'a',
            'b',
            'a',
            'b',
            'a',
            'a',
            'a'
        ];
        $result = [];

        for ($i = 0; $i < count($test); $i  ) {
            if ($i === 0 || $test[$i] !== $test[$i   1 !== count($test) ? $i   1 : 0]) {
                $result[] = $test[$i];
            }
        }

        dd($result);

Desired output:

['a', 'ba', 'ba', 'a', 'a']

CodePudding user response:

If the last item is b and current is a then they will be concatenated as ba at the same last index.

$array = array('a', 'b', 'a', 'b', 'a', 'a', 'a');

$result = array_reduce($array, function($acc, $item){
    // if has one item and last item is 'b' and current item is 'a'
    if(count($acc) > 0 &&  $acc[count($acc)-1] == "b" && $item=="a"){
      // make last item as 'ba'
      $acc[count($acc)-1] = "ba";
      return $acc;
    }
    array_push($acc, $item);
    return $acc;
}, array());

print_r($result); // Array ( [0] => a [1] => ba [2] => ba [3] => a [4] => a )

CodePudding user response:

I really don't understand the reason behind your logic, however the below code does what you are talking about, I think. At least, it matches your expected output.

If your sample data of a and b isn't representative of your actual data, for instance, it is free-form text of arbitrary length, this will definitely break.

See the code comments for how it works.

$result = [];

// The first two need to be setup manually. There should probably be a guard around this
// with a length check for $test.
$result[] = array_shift($test);
$result[] = array_shift($test);

// Inside the loop we'll keep removing items
while(count($test)){
    
    // Setup common variables
    $current = array_shift($test);
    $last = end($result);
    $last_char = $last[-1];
    
    if(strlen($last) >= 2){
        // If we have two (or more) characters at the end of the array, just append
        $result[] = $current;
    }elseif($current === $last_char){
        // Also, if we have the same character as last time, just append
        $result[] = $current;
    }else{
        // Otherwise we have a different character, so append the current to the previus
        $result[ count($result) - 1 ] = $last_char . $current;
    }
}

var_dump($result);

And here's an online demo: https://3v4l.org/0CS8m

  •  Tags:  
  • php
  • Related