Grouping php array items based on user and created time
This is an array of objects showing a user uploading photos:
Array
(
[12] => stdClass Object
(
[type] => photo
[created] => 2010-05-14 23:36:41
[user] => stdClass Object
(
[id] => 760
[username] => mrsmith
)
[photo] => stdClass Object
(
[id] => 4181
)
)
[44] => stdClass Object
(
[type] => photo
[created] => 2010-05-14 23:37:15
[user] => stdClass Object
(
[id] => 760
[username] => mrsmith
)
[photo] => stdClass Object
(
[id] => 4180
)
)
)
However instead of showing:
mr smith uploaded one photo
mr smith uploaded one photo
I'd like to display:
- mr smith uploaded two photos
by grouping similar items, grouping by user ID and them having added them within, let's say 15 minutes of each other. So I'd like to get the array in this sort of shape:
Array
(
[12] => stdClass Object
(
[type] => photo
[created] => 2010-05-14 23:36:41
[user] => stdClass Object
(
[id] => 760
[username] => mrsmith
)
[photos] => Array
(
[0] => stdClass Object
(
[id] => 4181
)
[1] => stdClass Object
(
[id] => 4180
)
)
)
)
preserving the first item of the group and it's created time, and supplementing it with any other groupable photos and then unsetting any items that were grouped (so the final array doesn't have key 44 anymore as it was grouped in with 12).
The array contains other actions than just photos, hence the original keys of 12 and 44. I just can't figure out a way to do this efficiently. I used to use MySQL and PHP to do this but am trying to just use pure PHP for caching reasons.
Can anyone shed any insights? I thought about going through each item and seeing if I can group it with the previous one in the array but the previous one might not necessarily be relevant or even a photo. I've got tota开发者_如何学运维l brain freeze :(
If the entries are ordered by date you can do the following:
- Keep an array (let's call it
$foo
) with all the photos in a 15 minute window. Use the array as a FIFO list (usearray_shift
to remove items and$foo[] = ...
to add). - Iterate over the original array
- Check the date of the current item and remove from the beginning of
$foo
all the entries whose date is more than 15 minutes less than the current item. Once you find an item that for something that happened less than 15 minutes ago, you can stop (it's a one line for loop). - Iterate over the the entries in
$foo
- If a photo by the same person is found, then
- Alter the reference stored in
$foo
so that the new data is added - Remove the current item from the original array
- break from inner loop
- Alter the reference stored in
- If not
- Add a reference to the current item to the end
$foo
with$foo = &$var
.
- Add a reference to the current item to the end
- Check the date of the current item and remove from the beginning of
You may then reindex the original array with array_values to fill the gaps.
精彩评论