I need a bit of help with the below concept.
I have an array:
JavaScript
x
$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'
),
);
I would like to loop through it and select the “first IN” and “last OUT” based on “dateTime”. So I should be getting:
JavaScript
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 |
How is it possible to achieve this? Appreciate any help.
Thanks,
Advertisement
Answer
The way I would approach this is to:
Filter the RAW input array to the earliest
in
and the latestout
. We don’t need the rest of the results.Re-format that output in the format expected.
The dateTime
strings appear to be properly formatted time stamps (presumably from a mysqli database). Which is good because it means we can compare the timestamps with <
and >
.
Solution
JavaScript
// 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"];
}
Output
JavaScript
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',
),
)
Code without comments
JavaScript
$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"];
}