Array Comprehensions in Home

On this page 41

Array comprehensions provide a concise, readable syntax for creating and transforming collections. They combine mapping, filtering, and iteration into a single expression.

Table of Contents

Basic Syntax

Simple Array Comprehension

// Basic syntax: [expression for variable in iterable]
let numbers = [1, 2, 3, 4, 5]
let doubled = [x * 2 for x in numbers]
// Result: [2, 4, 6, 8, 10]

// Identity comprehension
let copy = [x for x in numbers]
// Result: [1, 2, 3, 4, 5]

Range-Based Comprehensions

// Using range
let squares = [x * x for x in 0..10]
// Result: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

// With step
let evens = [x for x in 0..20 step 2]
// Result: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

Filtering

With if Clause

// Syntax: [expression for variable in iterable if condition]
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// Filter even numbers
let evens = [x for x in numbers if x % 2 == 0]
// Result: [2, 4, 6, 8, 10]

// Filter and transform
let even*squares = [x * x for x in numbers if x % 2 == 0]
// Result: [4, 16, 36, 64, 100]

Multiple Conditions

// Multiple conditions with and
let filtered = [x for x in numbers if x > 3 and x < 8]
// Result: [4, 5, 6, 7]

// Complex conditions
let result = [x for x in numbers if x % 2 == 0 and x > 5]
// Result: [6, 8, 10]

Mapping

Transform Elements

let names = ["alice", "bob", "charlie"]

// Uppercase
let upper = [name.to*uppercase() for name in names]
// Result: ["ALICE", "BOB", "CHARLIE"]

// String formatting
let greetings = ["Hello, {}!".format(name) for name in names]
// Result: ["Hello, alice!", "Hello, bob!", "Hello, charlie!"]

Method Calls

let strings = ["  hello  ", "  world  ", "  !  "]

// Trim whitespace
let trimmed = [s.trim() for s in strings]
// Result: ["hello", "world", "!"]

// Chain operations
let processed = [s.trim().to*uppercase() for s in strings]
// Result: ["HELLO", "WORLD", "!"]

Nested Comprehensions

Flattening Lists

// Nested comprehension: [expr for x in iter1 for y in iter2]
let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

// Flatten matrix
let flat = [x for row in matrix for x in row]
// Result: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Cartesian Product

let colors = ["red", "green", "blue"]
let sizes = ["S", "M", "L"]

// All combinations
let products = [
    "{}-{}".format(color, size)
    for color in colors
    for size in sizes
]
// Result: ["red-S", "red-M", "red-L", "green-S", "green-M", "green-L", "blue-S", "blue-M", "blue-L"]

Nested with Filter

let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

// Flatten and filter
let filtered = [x for row in matrix for x in row if x % 2 == 0]
// Result: [2, 4, 6, 8]

// Transform nested data
let doubled = [x * 2 for row in matrix for x in row if x > 3]
// Result: [8, 10, 12, 14, 16, 18]

Dictionary Comprehensions

Basic Dict Comprehension

// Syntax: {key*expr: value*expr for variable in iterable}
let numbers = [1, 2, 3, 4, 5]

// Number to square mapping
let squares = {x: x * x for x in numbers}
// Result: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

// String to length mapping
let names = ["alice", "bob", "charlie"]
let lengths = {name: name.len() for name in names}
// Result: {"alice": 5, "bob": 3, "charlie": 7}

With Filtering

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// Only even numbers
let even*squares = {x: x * x for x in numbers if x % 2 == 0}
// Result: {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}

Transform Keys and Values

let data = [("a", 1), ("b", 2), ("c", 3)]

// Uppercase keys, doubled values
let transformed = {
    k.to*uppercase(): v * 2
    for (k, v) in data
}
// Result: {"A": 2, "B": 4, "C": 6}

Set Comprehensions

Unique Elements

// Syntax: {expression for variable in iterable}
let numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

// Unique values
let unique = {x for x in numbers}
// Result: {1, 2, 3, 4}

// Unique squares
let unique*squares = {x * x for x in numbers}
// Result: {1, 4, 9, 16}

With Filtering

let words = ["apple", "banana", "apricot", "blueberry", "avocado"]

// Unique first letters of words starting with 'a'
let first*letters = {
    word[0]
    for word in words
    if word.starts*with("a")
}
// Result: {'a'}

Generator Expressions

Lazy Evaluation

// Syntax: (expression for variable in iterable)
// Generators are lazy - elements computed on demand

let numbers = 0..1000000

// Generator (doesn't compute all values immediately)
let squares = (x * x for x in numbers)

// Only computes values as needed
for square in squares.take(5) {
    println("{}", square)
}
// Prints: 0, 1, 4, 9, 16

Memory Efficient

// Array comprehension - creates full array in memory
let big*array = [x * x for x in 0..1000000]  // Uses lots of memory

// Generator - computes on demand
let big*gen = (x * x for x in 0..1000000)    // Minimal memory

// Use in sum
let sum = big*gen.sum()  // Efficient

Best Practices

1. Keep It Simple

// Good - clear and concise
let evens = [x for x in numbers if x % 2 == 0]

// Avoid - too complex
let result = [
    x * y + z
    for x in range1
    for y in range2
    for z in range3
    if x > y and y > z and (x + y) % 2 == 0
]  // Consider using regular loops

2. Use Meaningful Variable Names

// Good
let user*names = [user.name for user in users]
let active*ids = [user.id for user in users if user.active]

// Avoid
let x = [u.n for u in us]
let y = [u.i for u in us if u.a]

3. Prefer Comprehensions for Simple Cases

// Good - simple transformation
let doubled = [x * 2 for x in numbers]

// Avoid - use regular loop for complex logic
let result = []
for x in numbers {
    if complex*condition(x) {
        let processed = complex*processing(x)
        if another*condition(processed) {
            result.push(processed)
        }
    }
}

4. Use Generators for Large Data

// Good - memory efficient
let sum = (x * x for x in 0..1000000).sum()

// Avoid - creates large array
let sum = [x * x for x in 0..1000000].sum()

5. Break Complex Comprehensions

// Avoid - hard to read
let result = [x * y for x in range1 for y in range2 if x > 0 if y > 0 if x + y < 10]

// Good - break into steps
let positive*x = [x for x in range1 if x > 0]
let positive*y = [y for y in range2 if y > 0]
let result = [
    x * y
    for x in positive*x
    for y in positive*y
    if x + y < 10
]

Common Patterns

Filter and Map

// Get lengths of long words
let words = ["a", "hello", "hi", "world", "hey"]
let long*lengths = [word.len() for word in words if word.len() > 2]
// Result: [5, 5, 3]

Extract Fields

struct User {
    name: string,
    age: i32,
    active: bool,
}

let users = [/* ... */]

// Extract names of active users
let active*names = [user.name for user in users if user.active]

// Extract ages
let ages = [user.age for user in users]

Transform Data Structures

// List of tuples to dict
let pairs = [("a", 1), ("b", 2), ("c", 3)]
let dict = {k: v for (k, v) in pairs}

// Dict to list of tuples
let items = [(k, v) for (k, v) in dict.items()]

Conditional Expressions

// Ternary in comprehension
let labels = [
    "even" if x % 2 == 0 else "odd"
    for x in 0..10
]
// Result: ["even", "odd", "even", "odd", ...]

String Processing

let text = "Hello World"

// Character codes
let codes = [c.to*code() for c in text]

// Uppercase vowels
let processed = [
    c.to*uppercase() if c in "aeiou" else c
    for c in text
]

Examples

Data Processing

let data = [
    {"name": "Alice", "score": 85},
    {"name": "Bob", "score": 92},
    {"name": "Charlie", "score": 78},
    {"name": "Dave", "score": 95},
]

// High scorers
let high*scorers = [
    item["name"]
    for item in data
    if item["score"] >= 90
]
// Result: ["Bob", "Dave"]

// Score mapping
let scores = {item["name"]: item["score"] for item in data}

Matrix Operations

let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

// Transpose
let transposed = [
    [row[i] for row in matrix]
    for i in 0..3
]
// Result: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

// Diagonal
let diagonal = [matrix[i][i] for i in 0..3]
// Result: [1, 5, 9]

File Processing

let lines = read*file("data.txt").lines()

// Non-empty lines
let content = [line for line in lines if line.trim().len() > 0]

// Parse numbers
let numbers = [
    line.parse::<i32>().unwrap()
    for line in lines
    if line.trim().len() > 0
]

See Also

Released under the MIT License.