1

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 on ROO_Id and RAT_Id.

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

So, the desired output is:

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
          )
     )
)

Here what I have tried:

$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.

0

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

Comments

0

There is absolutely no reason to be making all of those iterated function calls.

Use a nested loop to iterate the subset of data for each room, group on the room "rate id", and push all "available date" values into a subarray in the respective group. When the subset of data is fully iterated, push its grouped data into the result array.

Code: (Demo)

$result = [];
foreach ($newArr as $rooId => $rows) {
    $groups = [];
    foreach ($rows as $row) {
        if (!isset($groups[$row['RAT_Id']])) {
            $row['AVA_Date'] = (array) $row['AVA_Date'];
            $groups[$row['RAT_Id']] = $row;
        } else {
            $groups[$row['RAT_Id']]['AVA_Date'][] = $row['AVA_Date'];
        }
    }
    $result[$rooId] = array_values($groups);
}
var_export($result);

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,
    ),
  ),
)

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.