December Code

Swift collections interview questions, with answers

Array, Set and Dictionary are value types in Swift, generic over their elements, and they share a large protocol-based toolkit of methods. Interviews check that a candidate picks the right collection, reads from it safely, and knows the quirks of strings and slices, which trip up developers coming from other languages.

The answers below cover the three main collections, safe dictionary lookups, filter and map, dictionary iteration, sets, strings as collections and array slices, with code compiled with swiftc 6.4. Then take the free Swift diagnostic — ten questions across every Swift topic in the bank — to see which of these you can explain but not yet predict.

The questions, with answers

  1. 1.What are Swift's main collection types?

    In short: Array is an ordered list, Set an unordered collection of unique values, and Dictionary an unordered map from unique keys to values.

    Array keeps elements in order and allows duplicates, with fast access by position. Set stores unique, Hashable elements in no particular order and answers membership questions quickly, so Set(a) below drops the duplicate 3. Dictionary maps unique Hashable keys to values, also without a defined order. All three are generic value types, so a copy is independent, and they are declared with let when they should not change. Choosing by the operations you need, ordered access, uniqueness or lookup by key, keeps code both clear and fast.

    let a = [3, 1, 3]
    let s = Set(a)
    print(a.count, s.count)
    // 3 2
  2. 2.How do you read a value from a Swift dictionary?

    In short: Subscripting with a key returns an optional, nil when the key is missing; the default: form returns a fallback instead.

    Because a key may be absent, dict[key] has an optional type and must be unwrapped, commonly with ?? or if let. The subscript with a default, dict[key, default: 0], returns a non-optional value, which also makes it convenient for counting with dict[key, default: 0] += 1. For iteration, keys and values give the two sides separately, and for transformation, mapValues and filter return new dictionaries. The optional result is Swift's way of making a missing key a case you must handle rather than an exception.

    let stock = ["pen": 4]
    print(stock["pen"] ?? 0)
    print(stock["ink", default: 0])
    // 4
    // 0
  3. 3.How do filter and map work on Swift arrays?

    In short: filter keeps the elements a closure accepts and map transforms each element, both returning new arrays and leaving the original unchanged.

    filter calls a closure for each element and returns an array of those for which it returns true. map calls a closure for each element and returns an array of the results, which may be a different type, as the marks become strings below. Both return new arrays, so they chain naturally, and each line of a chain can stay short. flatMap flattens nested arrays, sorted returns an ordered copy, and lazy defers the work until elements are actually needed.

    let marks = [72, 45, 90]
    let passed = marks
        .filter { $0 >= 50 }
        .map { "\($0)%" }
    print(passed)
    // ["72%", "90%"]
  4. 4.In what order does Swift iterate over a dictionary?

    In short: In no guaranteed order; sort the keys, or use an ordered structure, when the order matters.

    Dictionary is a hash table, and its iteration order depends on hashing, which Swift deliberately randomises per process, so the same code can print entries in a different order on each run. Code that needs a stable order must impose one, for example by iterating over keys.sorted(), as below, or sorting the key-value pairs by value. When insertion order itself matters, keep an array of keys alongside the dictionary or use OrderedDictionary from the swift-collections package.

    let d = ["b": 2, "a": 1]
    for k in d.keys.sorted() {
        print(k, d[k]!)
    }
    // a 1
    // b 2
  5. 5.When should you use a Set instead of an Array in Swift?

    In short: Use a Set when elements must be unique and you mainly test membership; use an Array when order or duplicates matter.

    A Set stores each element once, so inserting an element that is already present changes nothing, as the second insert of ios shows, and contains runs in constant time on average instead of scanning. Sets also provide union, intersection, subtracting and isSubset(of:), which make questions such as which tags two posts share one-liners. Elements must be Hashable. An Array is the better choice when you need positions, duplicates or a stable order. Converting between them is cheap to write: Set(array) and Array(set).

    var tags: Set = ["ios", "mac"]
    tags.insert("ios")
    print(tags.count)
    print(tags.contains("mac"))
    // 2
    // true
  6. 6.Why is a Swift String's count different from its UTF-8 size?

    In short: count counts Characters, which are grapheme clusters, while utf8.count counts the bytes of their UTF-8 encoding.

    A Swift String is a collection of Characters, and each Character is what a reader sees as one letter, however many Unicode scalars and bytes it takes. In "héllo", é is one Character but two UTF-8 bytes, so count is 5 and utf8.count is 6. Because characters have variable size, finding the nth one means walking the string, so strings are indexed with String.Index values and helpers such as prefix, dropFirst and firstIndex(of:). The utf8, utf16 and unicodeScalars views expose the lower levels when needed.

    let w = "héllo"
    print(w.count)
    print(w.utf8.count)
    print(w.prefix(2))
    // 5
    // 6
    // hé
  7. 7.What is an ArraySlice in Swift?

    In short: A view into part of an array that shares its storage and keeps the original array's indices rather than starting from 0.

    Subscripting an array with a range, as a[1...2], returns an ArraySlice rather than a new Array. The slice shares storage with the array, so creating it is cheap, but it keeps the original indices: its first element is at index 1 here, not 0, so code that assumes slices start at 0 is a common mistake. Use startIndex, first or iteration instead of fixed positions, and convert with Array(slice) when the result should be independent or stored long-term, since a slice keeps the whole original array's storage alive.

    let a = [10, 20, 30, 40]
    let mid = a[1...2]
    print(mid, mid.startIndex)
    // [20, 30] 1

How the diagnostic asks it

One question from the Swift bank, exactly as a sitting would show it. The bank has 3 on collections and 30 across Swift.

Collections · mediumSWIFT-023

What happens when this Swift code is compiled and run?

let s = "swift"
let c = s[1]
print(c)
  1. 1w
  2. 2It does not compile: a String cannot be indexed with an Intcorrect
  3. 3s
  4. 4It crashes at run time

Swift strings are collections of Characters, each of which may be several Unicode scalars and bytes long, so finding the nth character means walking the string. Swift makes that cost explicit by not offering an Int subscript: the compiler reports that subscripting a String with an Int is unavailable. s[s.index(s.startIndex, offsetBy: 1)] returns w, and Array(s)[1] does too. w and s are the answers of languages with Int string indexing, zero-based and one-based. There is no run-time crash because it never compiles.

Measure it

Reading answers tells you what’s true. A diagnostic tells you what you get wrong.

10 Swift questions across its topics, easy to hard, about fifteen minutes. You get a readiness figure with the arithmetic shown, the topics you missed named, and a practice set sized for today. Free: 1 diagnostic a month and 15 problems a day. No card.

What the readiness test measures · how the score is computed

By Harshit · updated