如何基于 PHP 中的父循环合并数组

huangapple go评论58阅读模式
英文:

How to merge arrays based on parent loop in PHP

问题

$mergedArray = [];

foreach ($rooms as $room) {
    $roomInfo = [];
    foreach ($paymentMethods as $payment) {
        $paymentInfo = [];
        foreach ($patients as $patient) {
            if ($patient->roomCode == $room->roomCode && $patient->paymentCode == $payment->paymentCode) {
                $paymentInfo[] = ['fullName' => $patient->fullName];
            }
        }
        $roomInfo[$payment->paymentName] = $paymentInfo;
    }
    $mergedArray[$room->roomName] = $roomInfo;
}
英文:

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?

答案1

得分: 3

在你的代码中,$room 是一个数组,并尝试将其用作键 ($mergedArray[$room])。这是无法正常工作的原因,也是你收到错误消息的原因。

如果你首先使用关联数组按其相关代码键入房间名称和付款方式名称,将更有效(并且更优雅):

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

一旦你有了这个,你只需要一个循环:

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

现在 $merged 是:

[
  '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'],
    ],
  ],
]

这样,你在结果中就不会得到那些空的付款槽。如果你真的也想要这些空槽,那么首先用空数组初始化目标结构:

$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];
}

如果房间和支付的组合数少于居住在设施中的患者数量,这仍然更有效。

英文:

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.

答案2

得分: 1

试一下这个:

编辑:通过添加if语句更正了解决方案。

$mergedArray = [];

foreach ($rooms as $room) {
    // 为收集付款创建空数组
    $mergedArray[$room["roomName"]] = [];
    
    foreach ($paymentMethods as $payment) {
        // 为稍后填充患者创建空数组
        $mergedArray[$room["roomName"]][$payment["paymentName"]] = [];
        
        foreach ($patients as $patient) {
            // 推送患者,因为键'fullName'是重复的
            // 不能使用相同的键添加另一个键值对。
            if ($patient["roomCode"] == $room["roomCode"] && $patient["paymentCode"] == $payment["paymentCode"]) {
                array_push(
                $mergedArray[$room["roomName"]][$payment["paymentName"]],
                ["fullName" => $patient["fullName"]]);
            }
            
        }
    }
}

print_r($mergedArray);
英文:

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

huangapple
  • 本文由 发表于 2023年3月8日 14:49:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定