Part of Swift with Copilot

Swift: Add 1 to each element in the array

Sandy LaneSandy Lane

Video: Swift: Add 1 to each element in the array by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

Swift with Copilot: Add 1 to Each Element in an Array

arr.map { $0 + 1 }. The simplest demonstration of map. For in-place: for i in arr.indices { arr[i] += 1 }.

The "increment every element" task. Pure-functional with map; imperative with a loop.

The Copilot prompt

// Add 1 to each element in the array
let numbers = [1, 2, 3, 4, 5]

Copilot completes:

let numbers = [1, 2, 3, 4, 5]
let plusOne = numbers.map { $0 + 1 }
print(plusOne)
// [2, 3, 4, 5, 6]

map: the canonical pattern

map is "for every element, give me a new element." Returns a new array of the same length:

[1, 2, 3].map { $0 + 1 }      // [2, 3, 4]
[1, 2, 3].map { $0 * 2 }      // [2, 4, 6]
[1, 2, 3].map { String($0) }   // ["1", "2", "3"]
[1, 2, 3].map { $0 > 0 }      // [true, true, true]

The output type can differ from the input — map is generic over the closure's return type.

In-place mutation

If you want to modify the original array:

var numbers = [1, 2, 3, 4, 5]
for i in numbers.indices {
  numbers[i] += 1
}
print(numbers)
// [2, 3, 4, 5, 6]

indices gives you the valid index range. Iterate, modify by index.

For arrays specifically, you could do:

numbers = numbers.map { $0 + 1 }

Same effect. The var is required because let is immutable.

In Swift, prefer immutable + map (clearer, no shared state). In-place is for performance-critical loops over huge arrays.

Adding from another array

let a = [1, 2, 3]
let b = [10, 20, 30]
let sums = zip(a, b).map { $0 + $1 }
// [11, 22, 33]

zip(a, b) produces pairs (a[0], b[0]), (a[1], b[1]), .... The closure takes the tuple and adds.

If the arrays differ in length, zip truncates to the shorter one.

Adding a constant from a variable

let bonus = 10
let scores = [85, 92, 78]
let final = scores.map { $0 + bonus }
// [95, 102, 88]

Closures capture variables from the enclosing scope. bonus is read inside the closure even though it's not a parameter.

With index

If you need both index and value:

let arr = [10, 20, 30]
let result = arr.enumerated().map { (i, x) in i + x }
// [10, 21, 32]

enumerated() yields (index, element) tuples. The closure unpacks with (i, x).

map returns Array

let r1 = [1, 2, 3].map { $0 + 1 }   // [Int]
let r2 = (1...3).map { $0 + 1 }     // [Int] — Range maps to Array

let r3 = "abc".map { $0 }           // [Character]
let r4 = ["a", "b"].joined().map { $0 }   // [Character]

map always returns an Array. For a lazy view, use lazy.map(...):

let lazy = (1...1_000_000).lazy.map { $0 * 2 }
// no allocation; iterator pulls one at a time

Multiple transforms

let result = [1, 2, 3, 4]
  .map { $0 + 1 }
  .filter { $0 % 2 == 0 }
  .map { $0 * 10 }
// [20, 40]

Chain freely. Each map/filter allocates a new array — for huge arrays, use lazy to fuse:

let result = [1, 2, 3, 4]
  .lazy
  .map { $0 + 1 }
  .filter { $0 % 2 == 0 }
  .map { $0 * 10 }
let materialized = Array(result)

lazy defers computation; iteration triggers each step on demand.

compactMap: filter + transform

If your transform might return nil:

let strings = ["1", "2", "abc", "4"]
let nums = strings.compactMap { Int($0) }
// [1, 2, 4] — "abc" dropped

compactMap flattens [T?] to [T], dropping nils. Common for parsing.

flatMap: flatten

If your transform returns an array (and you want it flat):

let words = ["hello world", "swift"]
let chars = words.flatMap { $0 }   // [Character]
// ["h", "e", "l", "l", "o", " ", "w", ...]

let nested = [[1, 2], [3, 4], [5]]
let flat = nested.flatMap { $0 }
// [1, 2, 3, 4, 5]

Common stumbles

map doesn't mutate. It returns a new array. Use let result = arr.map ... or assign back: arr = arr.map ....

map on huge array. Allocates. Use lazy for large pipelines.

Closure returns wrong type. arr.map { $0 + "x" } on [Int] errors. Match the closure to your goal.

Force-unwrap inside closure. [1, 2, 3].map { Int(String($0))! } — works but compactMap is cleaner if any might fail.

map for side effects. Wastes the array. Use forEach { print($0) } or a for-in loop.

Index-based loop with count. for i in 0..<arr.count works but arr.indices is preferred — handles non-zero start indices for slices.

What's next

Episode 16: Merge 2 integer arrays. Concatenation patterns.

Recap

arr.map { $0 + 1 } returns a new array with each element incremented. map is one-to-one; for filter+transform use compactMap; for flatten use flatMap. For huge pipelines, arr.lazy.map(...) defers allocation. For zip-based math, zip(a, b).map { $0 + $1 }. For in-place: for i in arr.indices { arr[i] += 1 }.

Next episode: array merging.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.