【问题标题】:Compare array values and selecting specific one比较数组值并选择特定的值
【发布时间】:2021-01-27 19:00:25
【问题描述】:

我需要一些关于以下概念的帮助。

我有一个数组:

$values = array(
    array(
        'logId'     => 1000,
        'userId'    => 1111,
        'dateTime'  => '2021-01-04 08:10:50',
        'event'     => 'OUT'
    ),
    array(
        'logId'     => 1001,
        'userId'    => 1111,
        'dateTime'  => '2021-01-04 08:11:50',
        'event'     => 'IN'
    ),
    array(
        'logId'     => 1002,
        'userId'    => 1111,
        'dateTime'  => '2021-01-04 08:11:53',
        'event'     => 'IN'
    ),
    array(
        'logId'     => 1003,
        'userId'    => 1111,
        'dateTime'  => '2021-01-04 17:10:50',
        'event'     => 'OUT'
    ),
    array(
        'logId'     => 1004,
        'userId'    => 2222,
        'dateTime'  => '2021-01-04 08:10:50',
        'event'     => 'IN'
    ),
    array(
        'logId'     => 1005,
        'userId'    => 2222,
        'dateTime'  => '2021-01-04 17:00:50',
        'event'     => 'OUT'
    ),
);

我想循环遍历它并根据“dateTime”选择“first IN”和“last OUT”。 所以我应该得到:

1 | 1001 | 1111 | 2021-01-04 08:11:50 | IN |
3 | 1003 | 1111 | 2021-01-04 17:10:50 | OUT |
4 | 1004 | 2222 | 2021-01-04 08:10:50 | IN |
5 | 1005 | 2222 | 2021-01-04 17:00:50 | OUT |

如何实现这一目标? 感谢任何帮助。

谢谢,

【问题讨论】:

  • edit您的问题并附上您尝试过但不起作用的代码。

标签: php arrays associative-array


【解决方案1】:

我的处理方法是:

  1. 将 RAW 输入数组过滤为最早的in 和最新的out。我们不需要其余的结果。

  2. 以预期的格式重新格式化该输出。

dateTime 字符串似乎是格式正确的时间戳(可能来自 mysqli 数据库)。这很好,因为这意味着我们可以将时间戳与<> 进行比较。

解决方案

// Define the filter array
$filterArray = [];

foreach($values as $log){

    // Set a reference to this userId in the new array
    $user = &$filterArray[$log["userId"]];


    // If nothing has been added for this person's IN/OUT yet then add it on here
    if(! ($user[$log["event"]] ?? null)){
        $user[$log["event"]] = $log;
    }

    // If the event is IN then check to see if this IN is earlier than the one already stored
    if($log["event"] == "IN" && $user["IN"]["dateTime"] > $log["dateTime"]){
        $user["IN"] = $log["dateTime"];
    }
    
    // If the event is OUT then check to see if this OUT is later than the one already stored
    if($log["event"] == "OUT" && $user["OUT"]["dateTime"] < $log["dateTime"]){
        $user["OUT"] = $log;
    }
}


// Sort by userId
ksort($filterArray);

// Define the output array
$outArray = [];

// Fill the output array
foreach($filterArray as $log){
    $outArray[] = $log["IN"];
    $outArray[] = $log["OUT"];

}

输出

array (
  0 => 
  array (
    'logId' => 1001,
    'userId' => 1111,
    'dateTime' => '2021-01-04 08:11:50',
    'event' => 'IN',
  ),
  1 => 
  array (
    'logId' => 1003,
    'userId' => 1111,
    'dateTime' => '2021-01-04 17:10:50',
    'event' => 'OUT',
  ),
  2 => 
  array (
    'logId' => 1004,
    'userId' => 2222,
    'dateTime' => '2021-01-04 08:10:50',
    'event' => 'IN',
  ),
  3 => 
  array (
    'logId' => 1005,
    'userId' => 2222,
    'dateTime' => '2021-01-04 17:00:50',
    'event' => 'OUT',
  ),
)

没有 cmets 的代码

$filterArray = [];
foreach($values as $log){
    $user = &$filterArray[$log["userId"]];
    if(! ($user[$log["event"]] ?? null)){
        $user[$log["event"]] = $log;
    }
    if($log["event"] == "IN" && $user["IN"]["dateTime"] > $log["dateTime"]){
        $user["IN"] = $log["dateTime"];
    }
    if($log["event"] == "OUT" && $user["OUT"]["dateTime"] < $log["dateTime"]){
        $user["OUT"] = $log;
    }
}
ksort($filterArray);
$outArray = [];
foreach($filterArray as $log){
    $outArray[] = $log["IN"];
    $outArray[] = $log["OUT"];
}

【讨论】:

    【解决方案2】:

    这段代码正是你想要的

    <?php
    
    $values = array(
        array(
            'logId'     => 1000,
            'userId'    => 1111,
            'dateTime'  => '2021-01-04 08:10:50',
            'event'     => 'OUT'
        ),
        array(
            'logId'     => 1001,
            'userId'    => 1111,
            'dateTime'  => '2021-01-04 08:11:50',
            'event'     => 'IN'
        ),
        array(
            'logId'     => 1002,
            'userId'    => 1111,
            'dateTime'  => '2021-01-04 08:11:53',
            'event'     => 'IN'
        ),
        array(
            'logId'     => 1003,
            'userId'    => 1111,
            'dateTime'  => '2021-01-04 17:10:50',
            'event'     => 'OUT'
        ),
        array(
            'logId'     => 1004,
            'userId'    => 2222,
            'dateTime'  => '2021-01-04 08:10:50',
            'event'     => 'IN'
        ),
        array(
            'logId'     => 1005,
            'userId'    => 2222,
            'dateTime'  => '2021-01-04 17:00:50',
            'event'     => 'OUT'
        ),
    );
    
    $users = [];
    foreach ($values as $value) {
        if (array_key_exists($value['userId'], $users)) {
            if (array_key_exists($value['event'], $users[$value['userId']])) {
                if ($value['event'] == 'OUT') {
                    if (($users[$value['userId']][$value['event']]['dateTime']) < ($value['dateTime'])) {
                        $users[$value['userId']][$value['event']]['dateTime'] = $value['dateTime'];
                        $users[$value['userId']][$value['event']]['logId'] = $value['logId'];
                    }
                }
    
                if ($value['event'] == 'IN') {
                    if (($users[$value['userId']][$value['event']]['dateTime']) > ($value['dateTime'])) {
                        $users[$value['userId']][$value['event']]['dateTime'] = $value['dateTime'];
                        $users[$value['userId']][$value['event']]['logId'] = $value['logId'];
                    }
                }
            } else {
                $users[$value['userId']][$value['event']] = [
                    'logId'     => $value['logId'],
                    'dateTime'  => $value['dateTime'],
                ];
            }
        } else {
            $users[$value['userId']][$value['event']] = [
                'logId'     => $value['logId'],
                'dateTime'  => $value['dateTime'],
            ];
        }
    }
    
    $counter = 1;
    foreach ($users as $key => $user) {
        echo "$counter ";
        echo $user['IN']['logId']." ";
        echo $key." ";
        echo $user['IN']['dateTime']." ";
        echo "IN ";
        echo PHP_EOL;
        $counter++;
        echo "$counter ";
        echo $user['OUT']['logId']." ";
        echo $key." ";
        echo $user['OUT']['dateTime']." ";
        echo "OUT ";
        echo PHP_EOL;
        $counter++;
    }
    

    输出

    1 1001 1111 2021-01-04 08:11:50 IN 
    2 1003 1111 2021-01-04 17:10:50 OUT 
    3 1004 2222 2021-01-04 08:10:50 IN 
    4 1005 2222 2021-01-04 17:00:50 OUT 
    

    在这个解决方案中,我创建了一组用户,每个用户都有这样的结构

        [1111] => Array
            (
                [OUT] => Array
                    (
                        [logId] => 1000
                        [dateTime] => 2021-01-04 17:10:50
                    )
    
                [IN] => Array
                    (
                        [logId] => 1001
                        [dateTime] => 2021-01-04 08:11:50
                    )
    
            )
    

    然后我使用 foreach 迭代数组并更新 INOUT,如果我找到更好的
    有什么问题可以问我

    【讨论】:

    • 您不需要与stringtotime 进行比较,因为dateTime 格式是合法的时间戳。 strtotime 所做的只是增加执行时间。
    • 那么if (strtotime($users[$value['userId']][$value['event']]['dateTime']) &lt; strtotime($value['dateTime'])) 的更好选择是什么?
    • 哦,我明白了,我可以删除strtotime,你是对的,很好:))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-12
    • 2020-10-22
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    相关资源
    最近更新 更多