← Home

036. Join() Method

Assemble sequences into strings efficiently

036. Join() Method

RAM Manager: Assembling Output Lines

Aryan’s RAM manager collects process data as lists and needs to output it as formatted lines. He’s building three assembler functions:

  • A CSV exporter (for piping to other tools)
  • A terminal table row (column display)
  • A breadcrumb path builder (for showing /proc paths)
# What he has
fields = ["chrome", "812", "544MB", "6.8%"]

# Bad (O(n²), trailing separator bug):
line = ""
for i, f in enumerate(fields):
    line += f
    if i < len(fields) - 1:
        line += ","
# → "chrome,812,544MB,6.8%"  (works but wrong way)

# Right way
line = ",".join(fields)

The sentence function has a subtle trailing-space bug that would corrupt his output. Fix all three.


💡 Fun fact: String concatenation in a loop (result += item) is O(n²) because each += creates a new string and copies all previous content — just like adding a brick to a wall by rebuilding the entire wall each time. str.join() pre-calculates the final length and allocates once, making it O(n). This difference becomes noticeable around 10,000+ strings.

⚠️ Watch out: join() requires all items to be strings",".join([1, 2, 3]) raises a TypeError. Beginners are surprised by this because print(1, 2, 3) auto-converts numbers, but join() does not. Always convert with str(x) or a list comprehension: ",".join(str(x) for x in numbers).

🤔 Think about it: "".join(["h","e","l","l","o"]) gives "hello". What does list("hello") give you? And if those two operations are inverses, why doesn’t Python just let you call "hello"[:] to get a list of characters like you can with a list slice?

Learning objectives

  • Use sep.join(list) to assemble strings
  • Understand join() is the inverse of split()
  • Prefer join() over string concatenation in loops

Key concepts

  • join()
  • string assembly
  • efficiency

Try it

Concept detail

sep.join(iterable) is the inverse of split(). It inserts sep between each item.

ALL items must be strings — join() does not auto-convert numbers: “,”.join([1, 2, 3]) → TypeError! “,”.join([str(x) for x in [1, 2, 3]]) → “1,2,3”

Performance: join() is O(n), loop concatenation is O(n²). Why? join() pre-calculates total length, then allocates one string. Each += in a loop allocates a new string and copies all previous content. For 1000 items: join does 1 allocation, loop does 1000 with increasing copy sizes.

Common patterns: “,”.join(fields) → CSV line “ “.join(words) → sentence “\n”.join(lines) → multi-line text “/”.join(path_parts) → filesystem path “”.join(chars) → reassemble character list into string

Edge cases: “x”.join([]) → “” (empty iterable → empty string) “x”.join([“a”]) → “a” (single item → no separator)

Solution

def csv_line(fields):
    return ",".join(fields)

def sentence(words):
    return " ".join(words)

def breadcrumb(parts):
    return " > ".join(parts)

Tests

def test_csv_line():
    assert csv_line(["Alice", "30", "Engineer"]) == "Alice,30,Engineer"

def test_csv_single():
    assert csv_line(["only"]) == "only"

def test_csv_empty():
    assert csv_line([]) == ""

def test_sentence():
    assert sentence(["hello", "world"]) == "hello world"

def test_sentence_no_trailing_space():
    result = sentence(["a", "b"])
    assert result == "a b", f"Got {repr(result)} — trailing space detected"

def test_breadcrumb():
    assert breadcrumb(["Home", "Products", "Laptop"]) == "Home > Products > Laptop"

def test_breadcrumb_single():
    assert breadcrumb(["Home"]) == "Home"

Resources