To keep synthetic Swift values unique without changing their insertion order, scan the input array once, track accepted keys in a set, and append only first occurrences to an output array. This guide builds a small local calculation you can run on a Mac.

The task is to process an ordered list of synthetic shape values, remove repeated values, and calculate a total from the retained entries. Everything happens in memory; the example reads no external input and saves no calculation results.

Define what “unique” means before choosing a collection

Swift arrays preserve order and allow duplicates. Sets contain unique values but have no defined ordering. Consequently, converting an array into a set and then back into an array does not preserve first-occurrence order. Sorting afterward establishes a sorting order, which may differ from insertion order. These collection behaviors are documented in Swift’s Collection Types.

For this example, each synthetic value has a shape name and a size. The default contract treats two entries as duplicates only when both properties match. A circle with size 12 and a circle with size 20 therefore remain separate values.

Contract question Rule for this calculation
What determines input order? Position in the supplied array
What makes two values duplicates? Equal shape and equal size
Which occurrence survives? The first occurrence
Does a later duplicate move the retained value? No
What happens with empty input? Return an empty array and a total of zero
Which values contribute to the total? Only retained values

This contract prevents an easy mistake: removing entries by shape name when the calculation needs distinct shape-and-size combinations. The worked example also calculates the shape-only result so you can see the consequence of changing that rule.

Build a complete local Swift example on your Mac

You need an installed Swift toolchain. In Terminal, run swift --version to confirm that the command is available. Swift’s official Build a Command-line Tool tutorial documents that check, executable package creation, and running a package.

Create a new directory for the example and initialize an executable package:

mkdir OrderDemo
cd OrderDemo
swift package init --name OrderDemo --type executable

Replace the generated executable source file under Sources with the complete program below. The generated filename and directory layout can vary with the toolchain; replace its existing entry point rather than adding a second one. This program uses an @main entry point, so place it in a file named OrderDemo.swift, renaming a generated main.swift if necessary. Swift’s command-line tutorial explains the choice between a main.swift file and an @main entry point.

No imports or package dependencies are required. The program uses standard-library types and functions.

struct Tile: Hashable {
    let shape: String
    let size: Int
}

func uniqueFirst<Value, Key: Hashable>(
    _ values: [Value],
    by key: (Value) -> Key
) -> [Value] {
    var seen: Set<Key> = []
    var result: [Value] = []

    for value in values {
        if seen.insert(key(value)).inserted {
            result.append(value)
        }
    }

    return result
}

@main
struct OrderDemo {
    static func main() {
        let input = [
            Tile(shape: "circle", size: 12),
            Tile(shape: "square", size: 8),
            Tile(shape: "circle", size: 12),
            Tile(shape: "circle", size: 20),
            Tile(shape: "square", size: 8)
        ]

        let retained = uniqueFirst(input, by: { $0 })
        let total = retained.reduce(0) { $0 + $1.size }
        let skipped = input.count - retained.count

        let expected = [
            Tile(shape: "circle", size: 12),
            Tile(shape: "square", size: 8),
            Tile(shape: "circle", size: 20)
        ]
        precondition(retained == expected)
        precondition(total == 40)
        precondition(skipped == 2)

        let empty: [Tile] = []
        precondition(uniqueFirst(empty, by: { $0 }).isEmpty)
        precondition(
            uniqueFirst([input[0], input[0]], by: { $0 })
                == [input[0]]
        )

        let byShape = uniqueFirst(input, by: { $0.shape })
        precondition(byShape == [input[0], input[1]])
        let shapeTotal = byShape.reduce(0) { $0 + $1.size }
        precondition(shapeTotal == 20)

        for tile in retained {
            print("\(tile.shape): \(tile.size)")
        }
        print("Total: \(total)")
        print("Skipped duplicates: \(skipped)")
        print("Shape-only total: \(shapeTotal)")
    }
}

From the package directory, run:

swift run OrderDemo

The expected program output, following any build messages, is shown below. The program was inspected against the retrieved API documentation but was not executed here because this research environment has no Swift executable.

circle: 12
square: 8
circle: 20
Total: 40
Skipped duplicates: 2
Shape-only total: 20

Why does the array-and-set approach preserve order?

The array is the sole source of output order. The loop visits each input position in sequence, and append(_:) places an accepted value at the end of the result. The set answers only whether the selected key has already appeared; the program never iterates over it.

The crucial expression is seen.insert(key(value)).inserted. Swift documents that insert(_:) returns inserted as true for a new member and false when an equal member already exists. An existing member remains unchanged. That return value lets one operation decide whether to append the original value. See Apple’s Set insertion documentation.

For the supplied input, the first circle and square are accepted. The second identical circle is skipped. The larger circle is accepted because its complete value differs, and the repeated square is skipped. The retained sizes are therefore 12 + 8 + 20 = 40.

The implementation maintains a useful invariant: after each iteration, the result contains exactly the earliest encountered value for every key in seen, in encounter order. A new key extends both collections; a repeated key changes neither. This reasoning explains the ordering guarantee independently of how the set stores its members.

How should custom Swift values express equality?

The declaration struct Tile: Hashable requests synthesized conformance. Both stored properties, String and Int, are hashable, so Swift can synthesize the required behavior. Apple documents these synthesis conditions in Hashable.

Using { $0 } as the key makes the whole Tile value determine uniqueness. Using { $0.shape } changes the contract to one retained entry per shape. In the example, that removes the later circle of size 20, reducing the total to 20. This is an intentional comparison between two rules, not a second implementation of the same rule.

Keep the key selection deterministic for the duration of the calculation. Derive it from the value being processed rather than a counter or changing external variable. Otherwise, equal inputs could receive different keys and survive as separate entries.

If you implement equality and hashing manually, use matching essential properties in both. Apple requires equal instances to feed the same values into the hasher in the same order. Avoid using hashValue itself as the uniqueness key: a hash is not a substitute for the value’s equality contract. Keeping the actual hashable key allows the set to apply that contract. See Hashable’s conformance requirements.

When should you use an ordered collection instead?

For this single calculation, an array plus a local set keeps the behavior explicit. If an application repeatedly appends, removes, reorders, and queries unique members, a dedicated ordered collection can make those operations easier to maintain.

Choice Suitable condition Relevant boundary
Array plus set One pass over synthetic Swift values, possibly using a selected key Your function defines first-occurrence behavior
Swift Collections OrderedSet Ongoing use of an ordered collection of unique hashable values Requires the separate Swift Collections package
Foundation NSOrderedSet An API already works with Foundation ordered object collections A class representing a static ordered collection; mutable operations use NSMutableOrderedSet

The official Swift Collections documentation describes OrderedSet as an ordered collection of unique elements, imported through OrderedCollections. It provides position-aware operations such as append(_:) and insert(_:at:). Those are package APIs, so adding import OrderedCollections alone does not configure an otherwise dependency-free project. See OrderedSet.

Apple’s Foundation documentation describes NSOrderedSet as a static ordered collection of distinct objects and identifies NSMutableOrderedSet as its mutable counterpart. For the native Swift value calculation above, the generic function expresses the chosen equality key directly without introducing that object collection. See NSOrderedSet.

What changes when the calculation feeds a desktop interface?

The complete example is synchronous and owns its temporary collections inside the function. For a small synthetic list, this gives one clear processing order without introducing tasks.

In a macOS interface, isolate UI-facing state and updates appropriately. Apple documents MainActor as a global actor whose executor is equivalent to the main dispatch queue; Swift’s concurrency guide explains applying @MainActor to functions and types that access interface state. See MainActor and Concurrency.

Concurrency also requires an explicit definition of order. Swift does not guarantee the completion order of child tasks in a task group. Appending results as tasks finish therefore preserves completion order, which can differ from the original input order. The official concurrency guide documents this boundary.

If a future version performs independent synthetic calculations concurrently, carry each input position alongside its result, restore input-position order after collection, and then apply the uniqueness pass. This is a design derived from that documented completion-order boundary. Keep the current small example synchronous unless additional work justifies the extra coordination.

Check the contract before reusing the function

The program includes checks for the exact retained order, empty input, repeated identical values, and the alternative shape-only rule. These checks target the decisions most likely to change the calculation’s meaning.

When adapting it, check three conditions: the input must already have a meaningful order, the key must express your intended equality rule, and retaining the first occurrence must be appropriate. The function deliberately skips later matching entries; it neither merges their sizes nor replaces the retained value. The reported skipped count makes that effect visible.

For the supplied synthetic shape list, the finished result is three values in first-occurrence order and a total of 40. Keep the array responsible for order, the set responsible for membership, and the selected key responsible for what “unique” means.

Sources