Search code examples
arrayslaravelcomparekeyvaluepair

Compare two arrays of objects having key value pair in laravel with specific key and return key value that don't match


I have two arrays: OrderItem:

[
    {
        "id": 4,
        "cancel": 0,
        "deleted_at": null,
        "created_at": "2020-08-12T10:14:01.000000Z",
        "updated_at": "2020-08-12T10:14:01.000000Z"
    },
    {
          "id": 3,
          "cancel": 0,
          "created_at": "2020-08-12T10:14:56.000000Z",
          "updated_at": "2020-08-12T10:14:56.000000Z",
    }
]

OrderReady:

[
    {
        "id": 2,
        "order_item_id": 4,
        "date": "1962-04-13",
        "wages": 12,
        "deleted_at": null,
        "created_at": "2020-08-12T10:14:56.000000Z",
        "updated_at": "2020-08-12T10:14:56.000000Z",
    }  
]

So I need to check id from OrderItem table with order_item_id in OrderReady table and return the record from OrderItam table in case the id does not exist in OrderReady table. From the data above, return record with id 3 of OrderItem table, since it does not appear in OrderReady table. What can be the most fastest and efficient way?


Solution

  • Here are two suggestions to how you can do it. You get an ugly way and a prettier way of doing it.

    First we iterate all the items and match with ready items. If no match is found, add that item to a list of "not ready items", for later processing.

    $orderItems = [
        ['id' => 1], ['id' => 2], ['id' => 3]
    ];
    
    $orderReadyItems = [
        ['order_item_id' => 1], ['order_item_id' => 3]
    ];
    
    // Array for storing items that are not yet ready
    $notReadyItems = [];
    
    foreach($orderItems as $item) {
        $itemReady = false;
        // Iterate all ready items and attempt to find a match with item.
        foreach($orderReadyItems as $orderReadyItem) {
            if ($item['id'] === $orderReadyItem['id']) {
                $itemReady = true;
                break; // Stop iterating ready items if a match is found.
            }
        }
    
        // Add item to $notReadyItems array if no match is found.
        if ($itemReady === false) {
            $notReadyItems[] = $item;
        }
    }
    

    To make this look a little prettier, we can take advantage of some of Collection methods. So instead of iterating all ready items, we instead create an array with all ready item ids and check that in a filter on orderItems, like so:

    $readyItemIds  = collect($orderReadyItems)->pluck('order_item_id');
    $notReadyItems = collect($orderItems)->filter(static function (array $item) use ($readyItemIds) {
        return !$readyItemIds->contains($item['id']);
    });
    

    Dumping $notReadyItems should give you:

    array:1 [
      0 => array:1 [
        "id" => 2
      ]
    ]