Group Photos and Sort Feed Items
NextdoorSoftware Engineer · Technical ScreenLast updated
Implement a feed transformation that collapses consecutive photo posts by the same user into album items and then stably sorts the resulting feed by timestamp.
Problem Statement
In a neighborhood social network, users frequently share single photos in quick succession. To prevent the main feed from feeling cluttered, the feed service collapses consecutive photo posts uploaded by the same user into a single album item before delivering the final feed to the client.
You are given a list of feed items in their original ingestion order. Each item is represented as a dictionary with the following structure:
id(str): Unique identifier of the item.user_id(str): Identifier of the author.type(str): Item type, either"photo"or"text".timestamp(int): Unix epoch timestamp in seconds.content(str): Text content or photo image URL.
Requirements
- Group Consecutive Photos: Scan the input feed in order. When two or more consecutive items have
type == "photo"and share the sameuser_id, group them into a single item oftype == "album".- A single photo not adjacent to another photo by the same user remains an individual
"photo"item unchanged. - The newly formed album item must have:
id:"album_" + first_photo_id(wherefirst_photo_idis theidof the earliest photo in the run).user_id: The author'suser_id.type:"album".timestamp: The maximumtimestampamong the photos in the group.photos: A list of strings containing thecontent(URLs) of the grouped photos in their original relative order.
- A single photo not adjacent to another photo by the same user remains an individual
- Sort Feed Items: After grouping, sort the transformed feed items in descending order of
timestamp.- If two or more items have identical timestamps, preserve their relative order from the grouped list (stable sort).
Function Signature
def transform_feed(items: list[dict]) -> list[dict]:
pass
Examples
Example 1
Input:
items = [
{"id": "p1", "user_id": "alice", "type": "photo", "timestamp": 100, "content": "url1.jpg"},
{"id": "p2", "user_id": "alice", "type": "photo", "timestamp": 105, "content": "url2.jpg"},
{"id": "t1", "user_id": "bob", "type": "text", "timestamp": 110, "content": "Hello neighbors!"},
{"id": "p3", "user_id": "alice", "type": "photo", "timestamp": 95, "content": "url3.jpg"}
]
Output:
[
{"id": "t1", "user_id": "bob", "type": "text", "timestamp": 110, "content": "Hello neighbors!"},
{"id": "album_p1", "user_id": "alice", "type": "album", "timestamp": 105, "photos": ["url1.jpg", "url2.jpg"]},
{"id": "p3", "user_id": "alice", "type": "photo", "timestamp": 95, "content": "url3.jpg"}
]
Explanation:
p1andp2are consecutive photos byalice, so they merge into an album with IDalbum_p1and timestampmax(100, 105) = 105.p3is separated fromp1andp2byt1, so it is not grouped with them.- Sorting by timestamp descending yields
t1(110), thenalbum_p1(105), thenp3(95).
Constraints
0 <= len(items) <= 100,000timestampis a non-negative integer (0 <= timestamp <= 2 * 10^9).user_id,id, andcontentare non-empty strings.typeis guaranteed to be either"photo"or"text".
Hints
Hint 1
Use a two-pointer approach or an iterative run-length grouping pass to identify contiguous slices of photos belonging to the same author.
Hint 2
Be careful to only collapse groups of size >= 2 into albums; single photos should retain their original fields.
Hint 3
Python's built-in `list.sort()` and `sorted()` are Timsort implementations, which are guaranteed to be stable.
Follow-up questions
- How would you handle a maximum album size constraint (e.g., at most 10 photos per album before starting a new album)?
- If the input stream is too large to fit in memory, how would you design this grouping and sorting pipeline?
- Suppose we also want to group photos that are separated by at most K seconds rather than strictly consecutive items. How would that change your data structures and complexity?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.