【问题标题】:How to get duplicate array out of an array如何从数组中取出重复的数组
【发布时间】:2019-12-14 11:15:04
【问题描述】:

我有一个订单数组。示例:

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

我想对这些订单进行排序。如您所见,可能有相同客户(具有相同电话号码的客户,可以是相同电话号码或相同手机号码)有多个订单的订单。我想将所有具有相同电话号码的订单(无论电话号码匹配还是手机号码都没有关系)放在数组 $duplicateOrders 中,所有“单一”订单(与电话号码不匹配的订单)放在一个数组 $singleOrders。最后,订单数组必须为空。但是没有顺序可以丢失或同时在两个数组中。

我尝试使用 foreach 循环遍历订单,在该循环中,我将每个订单放入 $singleOrders 数组并从 $orders 数组中取消设置。我尝试将该订单与另一个 foreach 循环匹配到 $orders 中的所有剩余订单。如果我得到一个匹配项,我会将该顺序(只完成一次)放入 $duplicateOrders 数组和它的每个匹配项中(我也从 $orders 数组中取消设置每个匹配项)。如果订单数组为空,我将停止,否则第一个 foreach 循环将启动并获取下一个订单并重复该过程。这是我的代码:

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

我希望有一个包含所有重复项的 $duplicateOrders 数组和一个包含所有单项的 $singleOrders 数组。我用一个包含 4 个订单的 $orders 数组对此进行了测试,其中 2 个是重复的,2 个是单次的。该函数很好地对其进行了排序(但仅当订单不是彼此紧接时,如果它们仍然对重复项进行正确排序,但在 $singleOrders 中也留下一个,并且我有 5 个订单)。比我在有 3 个重复和 1 个单一订单的情况下测试它。 $duplicateOrders 数组是正确的,但在 $singleOrders 中下单的订单,但也来自 $orders 数组的一个重复订单。它以某种方式正确删除了 2 个重复项,但在 $singleOrders 数组中留下了一个重复项。

有人可以帮我调试这个或提供不同的方法吗?我一直在尝试解决这个问题 2 天,但没有成功。

【问题讨论】:

  • 数据从何而来?不能退一步吗?我仍在尝试理解您描述的排序逻辑。
  • 订单是我的一个客户发给我的。大多数时候,每个客户只有一个订单,如果有第二个订单,他们只会调整第一个订单。但有时他们会犯错误,他们只会为同一个客户创建另一个订单。与他们发送给我的订单相比,他们有来自同一客户的 2 个订单。这就是我的客户所说的,但我可以想象,如果他们犯了这个错误,可能有 2 个具有相同电话号码的订单,也可能有超过 2 个具有相同电话号码的订单。这就是为什么我要检查每个订单是否重复
  • 好的,所以没有数据库。您将获得这种格式的数据。我会遍历它们并根据“唯一”约束重新索引。
  • 完全没有分贝。我以 JSON 格式得到它,必须处理它们并将结果发回。我不必存储任何数据
  • 那么在您的示例数组中,有 3 个重复订单,对吧?由于索引 0、1 和 3 的电话号码是相同的。

标签: php arrays laravel laravel-5 collections


【解决方案1】:

您可以使用Laravel Collections,在这种情况下,我将使用partition() 方法。来自文档:

partition()

partition 方法可以与list PHP 函数结合使用 将通过给定真值测试的元素与未通过的元素分开:

$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]

所以在你的情况下:

$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();

请注意,这两个新创建的对象($repeated$single)实际上也是 Collection class 的实例(如您所见,我在每个对象上都使用了 all() 方法),因此您可以保留在Collection's methods 的帮助下约束/排序/自定义它们。

【讨论】:

  • 为什么会被否决?在我更好地了解要求后,我会提出同样的建议。
  • 对不起。没有注意到laravel标签。已更正!
  • 谢谢。我会在早上试试这个。我必须在 4 小时后起床,我刚刚关掉了我的笔记本电脑。但如果它有效,我会回复你
  • @SunilKisoensingh 检查我所做的更正。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多