Word Count and Multiset Intersect Using Only a Mock Spark RDD API

Read the full interview experience this question came from →

Quick Overview

Given a minimal mock of a Spark RDD with only flatMap, groupByKey, union and collect, implement a word count function and a duplicate-preserving intersect of two RDDs. Tests composing transformations without map or reduce, tracking which input an item came from, and reasoning about the cost of grouping.

Word Count and Multiset Intersect Using Only a Mock Spark RDD API

Company: Datologyai

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: easy

Interview Round: Technical Screen

You are given a tiny, single-machine imitation of a Spark RDD. Using only the methods it provides, implement two new functions on top of it. ```python from collections import defaultdict class SimpleRDD: def __init__(self, items): self.items = items def flatMap(self, func): """Apply func to each item, flatten the results, and return a new SimpleRDD""" new_items = [] for item in self.items: new_items.extend(func(item)) return SimpleRDD(new_items) def groupByKey(self): """Group (key, value) pairs by key and return a SimpleRDD of (key, [values])""" grouped = defaultdict(list) for key, value in self.items: grouped[key].append(value) return SimpleRDD(list(grouped.items())) def union(self, other_rdd): """Return a new SimpleRDD containing items from self and other_rdd""" return SimpleRDD(self.items + other_rdd.items) def collect(self): """Return a list copy of the RDD items""" return list(self.items) ``` Note that the class has no `map`, `filter`, `reduceByKey` or `distinct`. ### Clarifying Questions - May a function call `collect()` and finish the work in plain Python, or must the result be built by chaining the provided transformations? - Must the result keep a particular order, or is any order of the output items acceptable? - Are the input items always hashable, given that `groupByKey` uses keys as dictionary keys? ### Part 1 — Word count Implement `word_count(rdd)`, which takes an RDD of sentences and returns an RDD that pairs each word with the number of times it appears. ```python sentences = SimpleRDD([ "hello world", "hello spark", "hello world" ]) wc_rdd = word_count(sentences) print(wc_rdd.collect()) # Output: [('hello', 3), ('world', 2), ('spark', 1)] ``` ```hint What flatMap can express List what each provided method can do. `flatMap` is more general than it looks: consider what it does when `func` returns a list with exactly one element, or an empty list. ``` #### Clarifying Questions for this Part - Are sentences split into words on whitespace only, or also on punctuation? - Are `"Hello"` and `"hello"` the same word? #### What This Part Should Cover - Expressing the missing map step with the provided methods - Turning grouped values into a count per word - Returning a `SimpleRDD`, and the order in which its items come out ### Part 2 — Intersect Implement `intersect(rdd1, rdd2)`, which takes two RDDs and returns an RDD of the items they have in common. ```python rdd1 = SimpleRDD([1, 3, 3]) rdd2 = SimpleRDD([3, 4, 3]) result = intersect(rdd1, rdd2) print(result.collect()) # Output: [3, 3] ``` The expected output keeps the repeated `3`, so this is not a plain set intersection. ```hint Bringing both sides together Think about which provided method can bring equal items from both inputs together, and what information is lost once the two inputs are merged. ``` #### Clarifying Questions for this Part - If a value appears twice in `rdd1` and three times in `rdd2`, how many copies belong in the result? The example (two copies on each side, two in the result) does not settle it. - Should the result follow the order of `rdd1`? #### What This Part Should Cover - Duplicate semantics that match the example, stated before coding - Combining both inputs while keeping track of which side each item came from - Time and memory cost, including a value that appears a very large number of times ### What a Strong Answer Covers - Recognizes that `flatMap` can stand in for the missing `map` and `filter` - Reproduces the example outputs exactly, including order and duplicates - Keeps the work inside RDD transformations rather than pulling all data to one place with `collect()` - Analyzes the time and memory of each function, including what `groupByKey` materializes - Tests edge cases such as empty inputs, irregular whitespace, and values present on only one side ### Follow-up Questions - How would you implement `distinct()` with only these methods, and how would its result on the Part 2 inputs differ from `intersect`? - In a real cluster, `groupByKey` ships every value across the network. If you could add one method to `SimpleRDD`, how would you make word count cheaper? - How would you implement an inner join of two RDDs of `(key, value)` pairs with the same building blocks?

Overview: Given a minimal mock of a Spark RDD with only flatMap, groupByKey, union and collect, implement a word count function and a duplicate-preserving intersect of two RDDs. Tests composing transformations without map or reduce, tracking which input an item came from, and reasoning about the cost of grouping.

Read the full Datologyai Software Engineer interview experience this question came from

|Home/Software Engineering Fundamentals/Datologyai
Datologyai logo
Datologyai
Jan 1, 2026
easySoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
0
0

You are given a tiny, single-machine imitation of a Spark RDD. Using only the methods it provides, implement two new functions on top of it.

from collections import defaultdict

class SimpleRDD:
    def __init__(self, items):
        self.items = items

    def flatMap(self, func):
        """Apply func to each item, flatten the results, and return a new SimpleRDD"""
        new_items = []
        for item in self.items:
            new_items.extend(func(item))
        return SimpleRDD(new_items)

    def groupByKey(self):
        """Group (key, value) pairs by key and return a SimpleRDD of (key, [values])"""
        grouped = defaultdict(list)
        for key, value in self.items:
            grouped[key].append(value)
        return SimpleRDD(list(grouped.items()))

    def union(self, other_rdd):
        """Return a new SimpleRDD containing items from self and other_rdd"""
        return SimpleRDD(self.items + other_rdd.items)

    def collect(self):
        """Return a list copy of the RDD items"""
        return list(self.items)

Note that the class has no map, filter, reduceByKey or distinct.

Clarifying Questions Guidance

  • May a function call collect() and finish the work in plain Python, or must the result be built by chaining the provided transformations?
  • Must the result keep a particular order, or is any order of the output items acceptable?
  • Are the input items always hashable, given that groupByKey uses keys as dictionary keys?

Part 1 — Word count

Implement word_count(rdd), which takes an RDD of sentences and returns an RDD that pairs each word with the number of times it appears.

sentences = SimpleRDD([
    "hello world",
    "hello spark",
    "hello world"
])
wc_rdd = word_count(sentences)
print(wc_rdd.collect())  # Output: [('hello', 3), ('world', 2), ('spark', 1)]

Clarifying Questions for this Part Guidance

  • Are sentences split into words on whitespace only, or also on punctuation?
  • Are "Hello" and "hello" the same word?

What This Part Should Cover Guidance

  • Expressing the missing map step with the provided methods
  • Turning grouped values into a count per word
  • Returning a SimpleRDD , and the order in which its items come out

Part 2 — Intersect

Implement intersect(rdd1, rdd2), which takes two RDDs and returns an RDD of the items they have in common.

rdd1 = SimpleRDD([1, 3, 3])
rdd2 = SimpleRDD([3, 4, 3])
result = intersect(rdd1, rdd2)
print(result.collect())  # Output: [3, 3]

The expected output keeps the repeated 3, so this is not a plain set intersection.

Clarifying Questions for this Part Guidance

  • If a value appears twice in rdd1 and three times in rdd2 , how many copies belong in the result? The example (two copies on each side, two in the result) does not settle it.
  • Should the result follow the order of rdd1 ?

What This Part Should Cover Guidance

  • Duplicate semantics that match the example, stated before coding
  • Combining both inputs while keeping track of which side each item came from
  • Time and memory cost, including a value that appears a very large number of times

What a Strong Answer Covers Guidance

  • Recognizes that flatMap can stand in for the missing map and filter
  • Reproduces the example outputs exactly, including order and duplicates
  • Keeps the work inside RDD transformations rather than pulling all data to one place with collect()
  • Analyzes the time and memory of each function, including what groupByKey materializes
  • Tests edge cases such as empty inputs, irregular whitespace, and values present on only one side

Follow-up Questions Guidance

  • How would you implement distinct() with only these methods, and how would its result on the Part 2 inputs differ from intersect ?
  • In a real cluster, groupByKey ships every value across the network. If you could add one method to SimpleRDD , how would you make word count cheaper?
  • How would you implement an inner join of two RDDs of (key, value) pairs with the same building blocks?
Loading comments...