0

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.

7
  • Where is the data coming from? Can't take a step back? I'm still trying to make sense of the sort logic you describe. Commented Aug 6, 2019 at 20:58
  • The orders are sent to me by a client of mine. Most of the times they only have one order for each client and if a second order comes in they just adjust the first order. But sometimes they make an error where they will just create another order for the same client. Than in the orders they sent to me they have 2 orders from the same client. Thats what my client said but I can imagine that if they make this error once where there can be 2 orders with the same phonenumber there can also be more than 2 orders with the same phonenumber. Thats why i want to check every order if its a duplicate Commented Aug 6, 2019 at 21:07
  • Ok, so no database. You are given data in this format. I'd iterate over them all and reindex by whatever the 'unique' constraint is. Commented Aug 6, 2019 at 21:08
  • Exactly no db. I get this in JSON format and have to proces them and send them back the results. I dont have to store any data Commented Aug 6, 2019 at 21:10
  • 1
    In your example array then, there are 3 duplicate orders, right? Since the phone number for index 0, 1 and 3 is the same. Commented Aug 6, 2019 at 21:21

1 Answer 1

2

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 the list 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.

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

4 Comments

Why is this downvoted? I was going to suggest the same thing after I understood the requirements better.
Sorry. Hadn't noticed the laravel tag. Corrected!
Thank you. I will try this in the morning. I have to get up in like 4 hours and i just turned off my laptop. But i will get back to you if it works or not
@SunilKisoensingh check the correction that I've made.

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.