'Check if a collection contain another collection?
Using Laravel Collection, what the good way to check if check if a collection ($selectedItems) contain another collection ($orders)?
I am currently using two foreach loop $selectedItems and check if it exist in the $orders using another loop.
$selectedItems = collect([
["ItemId" => "T123", "Price" => "12.00"],
["ItemId" => "T99", "Price" => "13.00"],
]);
$orders = collect([
["ItemId" => "T123", "Cost" => "12.00"],
["ItemId" => "T99", "Cost" => "13.00"],
["ItemId" => "T33", "Cost" => "13.00"],
]);
$found = [];
foreach ($selectedItems as $selectedItem)
{
foreach($orders as $orderItem)
{
if ($orderItem['ItemId'] !== $selectedItem['ItemId']) {
continue;
}
$found[] = $orderItem;
}
}
if (count($found) == $selectedItems->count()) {
dd("Matched");
} else {
dd("Not Matched");
}
How to also ensure the Price from $selectedItems is the same as Cost in the $orders
Solution 1:[1]
$selectedItems->diff($orders)->isEmpty();
This will diff the second collection from the first and if the result is empty you can be sure that all your items exist in the other collection.
Solution 2:[2]
$selectedItems = collect([
["ItemId" => "T123", "Price" => "12.00"],
["ItemId" => "T99", "Price" => "13.00"],
]);
$orders = collect([
["ItemId" => "T123", "Cost" => "12.00"],
["ItemId" => "T99", "Cost" => "13.00"],
["ItemId" => "T33", "Cost" => "13.00"],
]);
// get orders and selected items ids as an array
$ordersIds = array_map('array_shift', $orders->toArray());
$selectedItemIds = array_map('array_shift', $selectedItems->toArray());
// check selected items ids exist in orders ids
$exist = count(array_intersect($selectedItemIds, $ordersIds)) == count($selectedItemIds);
// if exist, return true
if ($exist)
return true;
Solution 3:[3]
I took a different approach than you to check if the $orders items keys are contained inside $selectedItems. But I think I got the expected result.
I created this function wrapping the code dealing with only this two arrays.
function checkContainsOrders($selectedItems, $orders)
{
//Commenting this lines that are necessary only for Laravel Collection
//$selectedItems = $selectedItems->toArray();
//$orders = $orders->toArray();
$selectedItemsKeys = array_column($selectedItems, 'ItemId');
$orderItemsKeys = array_column($orders, 'ItemId');
$intersectedValues = array_intersect($selectedItemsKeys, $orderItemsKeys);
if (count($intersectedValues) === count($selectedItems) || count($intersectedValues) === count($orders)) {
echo 'yup';
} else {
echo 'nope';
}
}
You can see that I'm making use of array_column to extract only the column I want from both arrays and array_intersect for finding the matches between both.
My data is declared as arrays only:
$selectedItems = [
["ItemId" => "T123", "Price" => "12.00"],
["ItemId" => "T99", "Price" => "13.00"],
];
$orders = [
["ItemId" => "T123", "Cost" => "12.00"],
["ItemId" => "T99", "Cost" => "13.00"],
["ItemId" => "T33", "Cost" => "13.00"],
];
But you can easily convert a collection to an array using the method toArray() as I commented in the code.
Then finally executing and validating the result.
checkContainsOrders($selectedItems, $orders);
This code has been tested here: https://3v4l.org/JlCC8
Solution 4:[4]
$matched = $selectedItems->intersect($orders)->count() == $selectedItems->count();
Intersect returns a collection of selectedItems found in Orders. When the count of this intersection == the count of the selectedItems then we know all selectedItems are in the interesected collection (and therefore all selectedItems are in Orders).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Aamir |
| Solution 2 | |
| Solution 3 | Rafael |
| Solution 4 | ChronoFish |
