Swift Filter Tutorial (With Examples)

You've got an array full of data. You only want some of it. That's exactly what Swift's filter is for.
Written by

Chris C

Updated on

Apr 06 2026

Table of contents

    Overview

    Swift's filter method lets you create a new array containing only the elements that match a condition. Instead of writing a loop, checking each item, and appending matches by hand, you describe the rule and let Swift do the scanning.

    Think of a recipe app showing only vegetarian recipes, a task app showing only incomplete tasks, or a score list showing only high scores. Those are all filtering problems.

    Basic Syntax

    The closure you pass to filter receives each element and returns true when Swift should keep that element.

    let filteredArray = array.filter { item in
        return condition
    }

    For each item, the closure answers one question: should this item stay in the new array?

    Filtering Numbers

    Here is a simple example that keeps only numbers greater than five:

    let numbers = [2, 8, 3, 11, 4, 9]
    
    let bigNumbers = numbers.filter { number in
        number > 5
    }
    
    print(bigNumbers)

    The result is [8, 11, 9]. The original numbers array does not change.

    Using Shorthand Syntax

    Swift lets you shorten simple filter closures with $0, which means the current element.

    let numbers = [2, 8, 3, 11, 4, 9]
    
    let bigNumbers = numbers.filter {
        $0 > 5
    }

    This version does the same thing as the named number in version. Shorthand is great for short conditions, but named parameters can be clearer when the logic grows.

    Filtering Strings

    Filter works with any array type, including strings.

    let names = ["Alex", "Maya", "Chris", "Ava"]
    
    let namesStartingWithA = names.filter {
        $0.hasPrefix("A")
    }
    
    print(namesStartingWithA)

    This keeps "Alex" and "Ava" because they pass the condition.

    Removing Empty Strings

    A common filter use case is cleaning up user input.

    let userInputs = ["Alice", "", "Bob", "", "Carol"]
    
    let nonEmptyInputs = userInputs.filter {
        !$0.isEmpty
    }
    
    print(nonEmptyInputs)

    Remember the mental model: return true for the values you want to keep. This example keeps strings that are not empty.

    Filtering Custom Structs

    In app code, you often filter arrays of your own models.

    struct Task {
        let title: String
        let isComplete: Bool
        let priority: Int
    }
    
    let tasks = [
        Task(title: "Study filter", isComplete: false, priority: 3),
        Task(title: "Submit app", isComplete: true, priority: 5),
        Task(title: "Fix bug", isComplete: false, priority: 5)
    ]
    
    let pendingTasks = tasks.filter { task in
        !task.isComplete
    }
    
    let highPriorityPendingTasks = tasks.filter { task in
        !task.isComplete && task.priority >= 5
    }

    Once the closure has a named parameter like task, you can access properties with normal dot syntax.

    Using Filter in SwiftUI Data

    In SwiftUI, filtered arrays are often expressed as computed properties derived from one source array.

    struct TaskListViewModel {
        var tasks: [Task]
    
        var pendingTasks: [Task] {
            tasks.filter { !$0.isComplete }
        }
    
        var urgentTasks: [Task] {
            tasks.filter { !$0.isComplete && $0.priority >= 5 }
        }
    }

    This keeps one source of truth and recalculates the filtered views from that source.

    Filter Does Not Modify the Original Array

    Filter returns a new array. It does not remove items from the original one.

    var items = [1, 2, 3, 4, 5]
    
    let oddItems = items.filter {
        $0 % 2 != 0
    }
    
    print(items)
    print(oddItems)

    If you want to actually remove items from a mutable array, use removeAll(where:).

    var items = [1, 2, 3, 4, 5]
    
    items.removeAll {
        $0 % 2 == 0
    }
    
    print(items)

    Filter vs CompactMap

    If your goal is to remove nil values from an array of optionals, use compactMap instead.

    let maybeNumbers: [Int?] = [1, nil, 3, nil, 5]
    
    let numbers = maybeNumbers.compactMap {
        $0
    }
    
    print(numbers)

    filter keeps or removes existing elements. compactMap can unwrap optionals and remove the nils in one step.

    Common Mistakes

    Forgetting to store the result

    Calling filter without using its return value does not change anything.

    numbers.filter { $0 > 5 }
    
    let bigNumbers = numbers.filter { $0 > 5 }

    Thinking in terms of what to remove

    Filter keeps elements where the closure returns true. Write the condition for what should remain.

    Using filter for complex transformations

    If you need to change each value, use map. If you need to transform values and remove nil results, use compactMap.

    Quick Reference

    SyntaxWhat It Does
    array.filter { $0 > value }Keeps elements greater than a value
    array.filter { $0.hasPrefix("A") }Keeps strings that start with a prefix
    array.filter { !$0.isEmpty }Removes empty strings
    array.filter { $0.isComplete }Keeps items where a Boolean property is true
    array.filter { item in item.a && item.b }Combines multiple conditions
    array.compactMap { $0 }Removes nil values from an optional array

    Summary

    • filter returns a new array containing only elements that pass a condition.
    • The closure returns true to keep an element and false to drop it.
    • The original array is not modified.
    • $0 is shorthand for the current element.
    • Filter works with arrays of numbers, strings, structs, classes, and any other Swift type.
    • Use removeAll(where:) when you want to mutate an existing array.
    • Use compactMap when you want to remove nil values from an optional array.

    The best way to get comfortable with filter is to find a loop that builds a smaller array and rewrite it as a filter call. After a few tries, the closure syntax starts to feel natural.