检查一个集合是否包含另一个集合?

Check if a collection contain another collection?

使用 Laravel 集合,检查一个集合 ($selectedItems) 是否包含另一个集合 ($orders) 的好方法是什么?

我目前正在使用两个 foreach 循环 $selectedItems 并使用另一个循环检查它是否存在于 $orders 中。

   $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");
    }

如何确保 $selectedItems 的价格与 $orders

的成本相同

你要的是union集合功能

它合并了集合并为您提供了一个独特的结果子集。这意味着删除了重复项。这样你就不必检查一个是否存在于另一个中,只需要你有一个具有唯一值的集合。

阅读有关联合函数的更多信息here

编辑:因为我误解了原文的意图这里是一个更符合意图的答案。

$found = [];
$selectedItems->contains(function ($value, $key) use ($found){
    if($orders->contains($value)) {
        $found += [$key => $value]
    }
})
$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;

我采用了与您不同的方法来检查 $orders 项键是否包含在 $selectedItems 中。但是我觉得我得到了预期的结果。

我创建了这个函数,包装了只处理这两个数组的代码。

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';
    }
}

您可以看到我正在使用 array_column 从两个数组中仅提取我想要的列,并使用 array_intersect 查找两者之间的匹配项。

我的数据仅声明为数组:

$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"],
];

但是您可以使用方法 toArray() 轻松地将 collection 转换为数组,正如我在代码中评论的那样。

然后最终执行并验证结果。

checkContainsOrders($selectedItems, $orders);

此代码已在此处测试:https://3v4l.org/JlCC8

$matched = $selectedItems->intersect($orders)->count() == $selectedItems->count();

相交 returns 在订单中找到的所选项目的集合。 当此交集的计数 == selectedItems 的计数时,我们知道所有 selectedItems 都在相交的集合中(因此所有 selectedItems 都在订单中)。

$selectedItems->diff($orders)->isEmpty();

这将区分第二个集合和第一个集合,如果结果为空,您可以确定您的所有项目都存在于另一个集合中。