使用哪个PHP数组函数?

使用哪个PHP数组函数?,php,arrays,filtering,Php,Arrays,Filtering,我对PHP中所有不同的数组函数感到非常困惑,我不知道在我的场景中使用哪一个是最好的 我有一个数组列出用户注册,还有一个数组列出用户订阅的日期。用户可以有多个订阅,也可以根本没有订阅。例如: $users = [ ['user_id' => 1, 'sign_up_date' => '2020-01-01 00:00:00'], ['user_id' => 2, 'sign_up_date' => '2020-01-02 00:00:00'], ['

我对PHP中所有不同的数组函数感到非常困惑,我不知道在我的场景中使用哪一个是最好的

我有一个数组列出用户注册,还有一个数组列出用户订阅的日期。用户可以有多个订阅,也可以根本没有订阅。例如:

$users = [
    ['user_id' => 1, 'sign_up_date' => '2020-01-01 00:00:00'],
    ['user_id' => 2, 'sign_up_date' => '2020-01-02 00:00:00'],
    ['user_id' => 3, 'sign_up_date' => '2020-01-03 00:00:00'],
    ...
];

$subscriptions = [
    ['user_id' => 1, 'subscription_category' => 'abc', 'sign_up_date' => '2020-01-01 00:01:00'],
    ['user_id' => 1, 'subscription_category' => 'def', 'sign_up_date' => '2020-01-01 00:02:00'],
    ['user_id' => 1, 'subscription_category' => 'ghi', 'sign_up_date' => '2020-01-02 00:03:00'],
    ['user_id' => 2, 'subscription_category' => 'jkl', 'sign_up_date' => '2020-01-02 00:01:00'],
    ['user_id' => 2, 'subscription_category' => 'mno', 'sign_up_date' => '2020-01-03 00:02:00'],
    ...
];
我试图找到的是哪些用户在他们的注册日期订阅了任何类别。因此,在本例中,我想查找以下项目的数量:

$usersWhoSubscribedOnSignUpDate = [1, 2];
我能做的是:

$results = [];
foreach ($users as $user) {
    foreach ($subscriptions as $subscription) {
        $signUpDate = date('Y-m-d', strtotime($user['sign_up_date']));
        $subscriptionDate = date('Y-m-d', strtotime($subscription['sign_up_date']));

        if ($subscription['user_id'] === $subscription['user_id'] && $signUpDate === $subscriptionDate) {
            $results[] = subscription['user_id'];
        }
    }
}
$results = array_unique($results);
array_unique(array_filter(
    $subscriptions,
    function ($subscription) use ($userDates) {
        return date('Y-m-d', strtotime($subscription['sign_up_date'])) ===
            $userDates[$subscription['user_id']];
    }
));
但在我看来,这并不是很优雅,我相信许多PHP数组函数中的一个可以以某种方式简化这个过程

array\u intersect
似乎不合适,因为它似乎不适合这样的多级数组

array\u map
似乎不合适,因为它无法比较两个数组


array\u uintercat\u assoc
似乎是一个选项,但我不明白“附加索引检查”是什么意思,也不知道如何对数据进行排序。我认为回调函数需要返回两个对象之间的比较,因此可能可以按
注册日期
属性的时间戳进行排序。

您可以在一次
$users
迭代和一次
$subscriptions
迭代中执行此操作,而不是在
$users
中每行重复一次
$subscriptions
。随着行数的增加,这可能会显著提高性能

首先,构建一个用户注册日期的关联数组,该数组由用户id索引,这样您就不必在每次需要查找日期时都对其进行迭代:

$userDates = [];
foreach ($users as $user) {
    $userDates[$user['user_id']] = date('Y-m-d', strtotime($user['sign_up_date']);
}
这将为您提供:

Array
(
    [1] => 2020-01-01
    [2] => 2020-01-02
    [3] => 2020-01-03
)
然后,只需在订阅上迭代一次,边走边查找该用户的注册日期:

foreach ($subscriptions as $subscription) {
    if (
        date('Y-m-d', strtotime($subscription['sign_up_date'])) ===
        $userDates[$subscription['user_id']]
    ) {
        ...
    }
}
或者类似于:

$results = [];
foreach ($users as $user) {
    foreach ($subscriptions as $subscription) {
        $signUpDate = date('Y-m-d', strtotime($user['sign_up_date']));
        $subscriptionDate = date('Y-m-d', strtotime($subscription['sign_up_date']));

        if ($subscription['user_id'] === $subscription['user_id'] && $signUpDate === $subscriptionDate) {
            $results[] = subscription['user_id'];
        }
    }
}
$results = array_unique($results);
array_unique(array_filter(
    $subscriptions,
    function ($subscription) use ($userDates) {
        return date('Y-m-d', strtotime($subscription['sign_up_date'])) ===
            $userDates[$subscription['user_id']];
    }
));

我想做的第一件事是修改数组,这样用户就可以通过键来识别(这是前两行)。第三行将每个用户的订阅日期缩短为最早,然后第四行查找注册日期和最早订阅日期匹配的位置

foreach( $users as $u ) { $signups[$u['user_id']] = date('Y-m-d', strtotime($u['sign_up_date']) ); }
foreach( $subscriptions as $s ) { $subs[$s['user_id']][] = date('Y-m-d', strtotime($s['sign_up_date']) ); }
foreach( $subs as $key => $value ) { $subs[$key] = min( $subs[$key] ); }
$results = array_keys( array_intersect_assoc( $signups, $subs ) );

如果您的数据存储在db?@u\u mulder中,也许您可以使用SQL查询。由于db中的一些不良结构以及缺乏资源或时间来重构,我们无法有效地在db中执行查找。
array\u column
有第三个参数,它消除了
array\u combine
的需要。啊,太好了,从未使用过。(但现在经过重构,不再每次都执行date())标记为解决方案,因为重新映射到使用用户ID作为密钥是一个很好的解决方案。