Reputation: 5
I have an array with orders. Example:
$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'
],
]
];
I want to sort these orders. As you can see there can be orders where the same customer (customer with same phone number, this can be either same phone number or same mobile number) has multiple orders. I want to put all the orders that have the same phone number (doesn't matter if the phone number matches or the mobile number) in an array $duplicateOrders and all the "single" orders (orders that dont match a phone number) in an array $singleOrders. At the end the orders array must be empty. But no order can be lost or be in both arrays.
I have tried to loop through the orders with a foreach loop where I put every order in the $singleOrders array and unset it from the $orders array. I than try to match that order with another foreach loop to all the remaining orders in $orders. If I get a match i put that order (this is done once) in the $duplicateOrders array and every match of it also (I unset every match also from the $orders array). If the orders array is empty I stop, otherwise the first foreach loops kicks in and takes the next order and the proces repeats. This is my code:
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++;
}
}
}
I expected to have an $duplicateOrders array with all the duplicates and a $singleOrders array with all the singles. I tested this with an $orders array of a total of 4 orders where 2 of them were duplicates and 2 were singles. The function sorted it nicely (but only if the orders aren't right after each other, if they are it still sorts the duplicates right but leaves one also in the $singleOrders and than I have 5 orders). Than I tested it where there were 3 duplicates and 1 single order. The $duplicateOrders array was correct but in the $singleOrders the single order was placed but also one duplicate order from the $orders array. It somehow removed the 2 duplicates correct but left one duplicate in the $singleOrders array.
Can someone help me to debug this or provide a different approach? I have been trying to solve this for 2 days but no success.
Upvotes: 0
Views: 83
Reputation: 14241
You could make use of Laravel Collections, in this case I'm gonna use the partition()
method. From the documentation:
partition()
The
partition
method may be combined with thelist
PHP function to separate elements that pass a given truth test from those that do not:$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]
So in your case:
$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();
Notice that this two newly created objects ($repeated
and $single
) are in fact also instances of the Collection class (as you can see where I used the all()
method on each), so you can keep constraining/sorting/customizing them with the help of the Collection's methods.
Upvotes: 2