Merge array depending key values in a multidimensional array in PHP

时间:2019-04-16 22:50:45

标签: php arrays

I've this type of array in PHP:

Array(
     [100] => Array(
          [1] => Array (
               [AVA_Date] => 2019-04-18
               [ROO_Id] => 100
               [RAT_Id] => 9
          )
          [2] => Array (
               [AVA_Date] => 2019-04-20
               [ROO_Id] => 100
               [RAT_Id] => 10
          )
          [4] => Array (
               [AVA_Date] => 2019-04-21
               [ROO_Id] => 100
               [RAT_Id] => 10
          )
          [7] => Array (
               [AVA_Date] => 2019-04-22
               [ROO_Id] => 100
               [RAT_Id] => 9
          )
     )
)

I would like to merge items in this array only if ROO_Id and RAT_Idare equals.

Then, for the AVA_Date, I need to list them under a new array in the curent array.

So, the desired output is:

Array(
     [100] => Array(
          [1] => Array (
               [AVA_Date] => Array (
                    [0] => 2019-04-18
                    [1] => 2019-04-22
               )
               [ROO_Id] => 100
               [RAT_Id] => 9
          )
          [2] => Array (
               [AVA_Date] => Array (
                    [0] => 2019-04-20
                    [1] => 2019-04-21
               )
               [ROO_Id] => 100
               [RAT_Id] => 10
          )
     )
)

Here what I have try:

$newArrOtherRooms  = array_reduce($newArr, function($acc, $val) {
    $room = array_search($val['ROO_Id'], array_column($acc, 'ROO_Id'));
    $rate = array_search($val['RAT_Id'], array_column($acc, 'RAT_Id'));
    if($rate == $room && $room > -1) {
        array_push($acc[$room]['AVA_Date'], $val['AVA_Date']);
    }
    else {
        $new_arr = $val;
        $new_arr['AVA_Date'] = [$val['AVA_Date']];
        array_push($acc, $new_arr);
    }
    return $acc;
},[]);

But it doesn't work like I want.

What I'm missing here please ?

Thanks for any help.

1 个答案:

答案 0 :(得分:2)

There are a couple of issues with your code. Firstly, you need to wrap the array_reduce with a foreach over the outer level of $newArr. Secondly, your call to array_search doesn't consider the fact that a ROO_Id or RAT_Id value might exist more than once in the array, as it only returns the first key at which it finds the value. To work around this, you can use array_keys to get an array of key values for each ROO_Id and RAT_Id value, and then take the intersection of those two arrays using array_intersect to see if both are present in the same element. If so, you update that element, otherwise you create a new one:

foreach ($newArr as $key => $array) {
    $newArrOtherRooms[$key]  = array_reduce($array, function($acc, $val) {
        $room = array_keys(array_column($acc, 'ROO_Id'), $val['ROO_Id']);
        $rate = array_keys(array_column($acc, 'RAT_Id'), $val['RAT_Id']);
        $common = array_intersect($room, $rate);
        if(!empty($common)) {
            array_push($acc[current($common)]['AVA_Date'], $val['AVA_Date']);
        }
        else {
            $new_arr = $val;
            $new_arr['AVA_Date'] = [$val['AVA_Date']];
            array_push($acc, $new_arr);
        }
        return $acc;
    },[]);
}
print_r($newArrOtherRooms);

Output:

Array(
     [100] => Array(
          [0] => Array (
               [AVA_Date] => Array (
                    [0] => 2019-04-18
                    [1] => 2019-04-22
               )
               [ROO_Id] => 100
               [RAT_Id] => 9
          )
          [1] => Array (
               [AVA_Date] => Array (
                    [0] => 2019-04-20
                    [1] => 2019-04-21
               )
               [ROO_Id] => 100
               [RAT_Id] => 10
          )
     )
)

Demo on 3v4l.org