我有一个包含订单的数组。示例:
$orders = [
'0' => [
'ordernumber' => 1,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
],
'1' => [
'ordernumber' => 2,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
],
'2' => [
'ordernumber' => 3,
'customer' => [
'phone' => '0987654321',
'mobile' => '0687654321'
],
],
'3' => [
'ordernumber' => 3,
'customer' => [
'phone' => '0123456789',
'mobile' => '0612345678'
],
]
];
我想对这些订单进行排序。如您所见,在同一客户(具有相同电话号码的客户,可以是同一电话号码或同一手机号码)下有多个订单的订单中。我想将所有具有相同电话号码的订单(无论电话号码匹配还是手机号码)都放在数组$ duplicateOrders中,而所有“单个”订单(不匹配电话号码的订单)都放在一个数组中数组$ singleOrders。最后,orders数组必须为空。但是不会丢失任何顺序,也不会同时出现在两个阵列中。
我尝试通过foreach循环遍历订单,在该循环中,我将每个订单放入$ singleOrders数组中,并从$ orders数组中取消设置。然后,我尝试将该订单与另一个foreach循环匹配到$ orders中的所有其余订单。如果找到匹配项,则将该订单(执行一次)放入$ duplicateOrders数组中,并且也将其匹配(我也将从$ orders数组中取消所有匹配项)。如果orders数组为空,我停止,否则第一个foreach循环开始并接受下一个订单,并且过程重复。这是我的代码:
protected function splitDuplicateOrders()
{
$singleOrderKey = 0;
if ($this->orders) {
foreach ($this->orders as $key => $order) {
if (count($this->orders) == 0) {
break;
}
array_push($this->singleOrders, $order);
unset($this->orders[$key]);
$orderPushed = false;
foreach ($this->orders as $otherKey => $value) {
if ($order->customer->phone == $value->customer->phone || $order->customer->mobile == $value->customer->mobile) {
if (!$orderPushed) {
array_push($this->duplicateOrders, $order);
}
array_push($this->duplicateOrders, $value);
unset($this->orders[$otherKey]);
unset($this->singleOrders[$singleOrderKey]);
$orderPushed = true;
}
}
$singleOrderKey++;
}
}
}
我希望有一个包含所有重复项的$ duplicateOrders数组和一个包含所有单项的$ singleOrders数组。我用$ orders数组(共4个订单)进行了测试,其中2个是重复的,2个是单身的。该函数对它进行了很好的排序(但仅在订单彼此不正确时才排序,如果它们仍然对重复项进行排序,但是在$ singleOrders中也留下了一个,则我有5个订单)。比我测试的地方有3个重复项和1个单项订单。 $ duplicateOrders数组是正确的,但在$ singleOrders中放置了单个订单,但在$ orders数组中也放置了一个重复订单。它以某种方式删除了正确的2个重复项,但在$ singleOrders数组中保留了一个重复项。
有人可以帮助我调试此问题或提供其他方法吗?我已经尝试解决了2天,但没有成功。
答案 0 :(得分:2)
您可以使用Laravel Collections,在这种情况下,我将使用partition()
方法。从文档中:
partition()
partition
方法可以与list
PHP函数结合使用以 将没有通过给定真相测试的元素与没有通过真相测试的元素分开:$collection = collect([1, 2, 3, 4, 5, 6]); list($underThree, $equalOrAboveThree) = $collection->partition(function ($i) { return $i < 3; }); $underThree->all(); // [1, 2] $equalOrAboveThree->all(); // [3, 4, 5, 6]
所以在您的情况下:
$orders = /** query or API to get orders as array */;
list($repeated, $single) = collect($orders)
->partition(function ($order) use ($orders) {
return $orders->where('customer.phone', $order['customer']['phone'])->count() > 1
OR $orders->where('customer.mobile', $order['customer']['mobile'])->count() > 1;
});
// now you can use them:
$repeated->all();
$single->all();
请注意,这两个新创建的对象($repeated
和$single
)实际上也是Collection class的实例(如您所见,我在哪里使用了all()
方法),因此您可以在Collection's methods的帮助下继续对其进行约束/排序/自定义。