Never Walk Alone

An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
easy
Seniority
L3
Asked in
JPMorgan Chase

Problem

Given a text string, split on whitespace and return a list of consecutive 2-word pairs, where each pair is a list [word_i, word_{i+1}]. Return an empty list if there are fewer than 2 words.

Every step is measured against the one before it.

Example 1

Input:

text = "the quick brown fox"

Output:

[["the","quick"],["quick","brown"],["brown","fox"]]

Example 2

Input:

text = "hello world"

Output:

[["hello","world"]]

Worked solution and explanation

Strip the costume and this is a width-2 sliding window over a token stream - bigrams, the thing every NLP pipeline builds before it does anything interesting. The window part is trivial; the whole problem lives in two decisions that look cosmetic and aren't. First, how you tokenize: reach for text.split(' ') and a tab or a double space quietly injects empty-string 'words' into your output, so 'sun moon stars' comes back with ['', ''] pairs that no grader will forgive. Second, how far you loop: iterate to len(words) instead of len(words) - 1 and the last step reads words[i + 1] off the end - IndexError, on the very input the interviewer hands you to check boundaries.

How a senior reasons through it

Step 1: Tokenize with the whitespace-collapsing split

words = text.split() - no argument. I pick this deliberately over split(' ') because the inputs include tabs and double spaces, and the bare split makes runs-of-whitespace a non-issue instead of a bug I have to patch later with a filter.

Step 2: Walk adjacent index pairs, not disjoint chunks

range(len(words) - 1) gives me every starting index that has a right-hand neighbor. Each interior word appears in two pairs - as the right of one and the left of the next - because it is a SLIDING window, not two-at-a-time chunking. Getting this wrong drops half the pairs.

Step 3: Let the bound handle the short inputs

I don't write a special case for empty or single-word text. When len(words) is 0 or 1, len(words) - 1 is -1 or 0, range() is empty, and the loop never runs - so I return [] automatically. The edge case is absorbed by the loop bound instead of a guard clause I could forget.

Sliding window of width 2 over tokens
def sequential_word_pairs(text):
    words = text.split()
    result = []
    for i in range(len(words) - 1):
        pair = [words[i], words[i + 1]]
        result.append(pair)
    return result

Bare split() for tokenizing; range(len(words) - 1) makes the short-input case disappear.

split(' ') - literal, fragile
'sun moon stars'.split(' ') -> ['sun moon', '', 'stars']. The tab stays glued inside a token and the double space yields a ''. Your pairs now contain garbage, and an empty input gives [''] (length 1, not 0).
split() - collapsing, robust
'sun moon stars'.split() -> ['sun', 'moon', 'stars']. Tabs and repeated spaces collapse, edges trim, and ''.split() -> [] cleanly. Same line of code, none of the failure modes.

Common follow-up questions