Reputation: 10828
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
Upvotes: 4
Views: 3941
Reputation: 41
$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.
Upvotes: 4
Reputation: 3707
$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).
Upvotes: 1
Reputation: 98
What you want is the union collection function.
It merges the collections and gives you a unique subset of results. Meaning that duplicates are removed. This way you don't have to check if one exists in the other, just that you have a collection with unique values.
Read more about the union function here
Edit: Because I misunderstood the intent of the original here is an answer that more correctly matches the intent.
$found = [];
$selectedItems->contains(function ($value, $key) use ($found){
if($orders->contains($value)) {
$found += [$key => $value]
}
})
Upvotes: 1
Reputation: 1535
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
Upvotes: 0
Reputation: 2866
$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;
Upvotes: 0