skip to Main Content

I have a dataset of patients , room and payment method (which is an array of objects). Those 3 arrays looks like this:

$rooms = [
   (object) [
      'roomCode' => 1,
      'roomName' => 'Room 1'
   ],
   (object) [
      'roomCode' => 2,
      'roomName' => 'Room 2'
   ],
   (object) [
      'roomCode' => 3,
      'roomName' => 'Room 3'
   ],
];

$paymentMethods = [
   (object) [
      'paymentCode' => 1,
      'paymentName' => 'Payment 1'
   ],
   (object) [
      'paymentCode' => 2,
      'paymentName' => 'Payment 2'
   ],
   (object) [
      'paymentCode' => 3,
      'paymentName' => 'Payment 3'
   ],
];

$patients = [
   (object) [
      'fullName' => 'Patient A',
      'roomCode' => 1,
      'paymentCode' => 1
   ],
   (object) [
      'fullName' => 'Patient B',
      'roomCode' => 1,
      'paymentCode' => 1
   ],
   (object) [
      'fullName' => 'Patient C',
      'roomCode' => 2,
      'paymentCode' => 1
   ],
   (object) [
      'fullName' => 'Patient D',
      'roomCode' => 1,
      'paymentCode' => 3
   ],
   (object) [
      'fullName' => 'Patient E',
      'roomCode' => 3,
      'paymentCode' => 3
   ],
];

What I’m expecting to achieve is to merge the patient array to room and payment method array to get their respective names based on the parent loop.

The expected array will kind of looks like this:

$mergedArray = [
   [
      'Room 1' => [
          'Payment 1' => [
             0 => ['fullName' => 'Patient A'],
             1 => ['fullName' => 'Patient B']
          ],
          'Payment 2' => [],
          'Payment 3' => [
             0 => ['fullName' => 'Patient D'],
          ]
      ],
      'Room 2' => [
          'Payment 1' => [
             0 => ['fullName' => 'Patient C']
          ],
          'Payment 2' => [],
          'Payment 3' => [],
      ],
      'Room 3' => [
          'Payment 1' => [],
          'Payment 2' => [],
          'Payment 3' => [
             0 => ['fullName' => 'Patient E']
          ],
      ],
   ]
];

I’ve tried using loop this way:

$mergedArray = [];

foreach ($rooms as $room) {
    $mergedArray[] = $room;
    foreach ($paymentMethods as $payment) {
        $mergedArray[$room] = $payment;
        foreach ($patients as $patient) {
            if ($patient->roomCode == $room->roomCode && $patient->paymentCode == $payment->paymentCode) {
                $mergedArray[$payment] = ['fullName' => $patient->fullName];
            }
        }
    }
}

Above code gave me Illegal offset type error. Any ideas how to achieve this?

2

Answers


  1. Try this one:

    Edit: solution corrected by adding if statement.

    $mergedArray = [];
    
    foreach ($rooms as $room) {
        //create empty array for collecting payments
        $mergedArray[$room["roomName"]] = [];
        
        foreach ($paymentMethods as $payment) {
            //create empty array for filling it with patients later.
            $mergedArray[$room["roomName"]][$payment["paymentName"]] = [];
            
            foreach ($patients as $patient) {
                //push patients because key 'fullName' is duplicate
                //you cant add another key-value pair with the same key. 
                if ($patient["roomCode"] == $room["roomCode"] && $patient["paymentCode"] == $payment["paymentCode"]) {
                    array_push(
                    $mergedArray[$room["roomName"]][$payment["paymentName"]],
                    ["fullName" => $patient["fullName"]]);
                }
                
            }
        }
    }
    
    print_r($mergedArray);
    
    Login or Signup to reply.
  2. In your code $room is an array, and there is an attempt to use it as a key ($mergedArray[$room]). That cannot work and is the reason for the error message you get.

    It will be more efficient (and elegant) if you first key your room names and payment method names by their relevant codes in associative arrays:

    $roomMap = array_column($rooms, "roomName", "roomCode");
    $paymentMap = array_column($paymentMethods, "paymentName", "paymentCode");
    

    Once you have that, you only need one loop:

    foreach($patients as $patient) {
        $merged[$roomMap[$patient->roomCode]][$paymentMap[$patient->paymentCode]][]
                                               = ["fullName" => $patient->fullName];
    }
    

    Now $merged is:

    [
      'Room 1' => [
        'Payment 1' => [
            ['fullName' => 'Patient A'],
            ['fullName' => 'Patient B'],
        ],
        'Payment 3' => [
            ['fullName' => 'Patient D'],
        ],
      ],
      'Room 2' => [
        'Payment 1' => [
            ['fullName' => 'Patient C'],
        ],
      ],
      'Room 3' => [
        'Payment 3' => [
            ['fullName' => 'Patient E'],
        ],
      ],
    ]
    

    This way you don’t get those empty payment slots in your result. If you really want those empty slots as well, then first initialise the targeted structure with empty arrays:

    $merged = [];
    foreach($roomMap as $roomName) {
        foreach($paymentMap as $paymentName) {
            $merged[$roomName][$paymentName] = [];
        }
    }
    foreach($patients as $patient) {
        $merged[$roomMap[$patient->roomCode]][$paymentMap[$patient->paymentCode]][] 
                                               = ["fullName" => $patient->fullName];
    }
    

    This will still be more efficient if the number of combinations of rooms and payments is less than the number of patients residing in the facility.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search