Swift: flatwhacking arrays

Obviously the best way to remove optionals from an array is this. You start with an array of optionals and flat-whack the heck out of them.

let results = arrayOfOptionals.flatMap({$0})

But where’s the fun in doing the obvious. Here are some other ways to flat-whack. Please add your own.

for case

var results = [String]()
for case let value? in arrayOfOptionals {results.append(value)}

flatMap with (ugly) forced unwrap

let results = arrayOfOptionals.flatMap{$0 == nil ? [] : [$0!]}

map and append

var results = [String]()
arrayOfOptionals.map({
    (optional : String?) -> Void in 
    if case let value? = optional {
        results.append(value)}
})

for / guard

results = [String]()
for optional in arrayOfOptionals {
    guard let unwrapped = optional else {continue}
    results.append(unwrapped)
}

or worse:

results = [String]()
for optional in arrayOfOptionals {
    do {
        guard let value = optional else {
            throw NSError(domain:"", code:0, userInfo:nil)}
        results += [value]
    } catch {}
}

flatmap / map

Thanks, Lily B

results = arrayOfOptionals.flatMap({
    $0.map({[$0]}) ?? [] })

reduce / combine

Thanks, Lily B

results = arrayOfOptionals.reduce(
    [], combine: { $1 == nil ? $0 : $0 + [$1!] })

split / flat / flat

results = split(arrayOfOptionals, 
    isSeparator: {$0 == nil
        }).flatMap({$0}).flatMap({$0})

filter / map

results = arrayOfOptionals.filter({
    $0 != nil}).map{$0!}

recurse

func squeezle(var arrayOfOptionals : [String?]) -> [String] {
    if arrayOfOptionals.isEmpty {return []}
    if let last = arrayOfOptionals.removeLast() {
        return squeezle(arrayOfOptionals) + [last]
    } else {return squeezle(arrayOfOptionals)}
}
results = squeezle(arrayOfOptionals)

3 Comments

  • arrayOfOptionals.reduce([Int]()) { (var a, e) in
        if let e = e {
            a.append(e)
        }
        return a
    }

    or

    for e in arrayOfOptionals where e != nil {
        a.append(e!)
    }
  • func flattenGen(var gen: G) -> [T] {
      return gen.next().map { ($0.map { [$0] } ?? []) + flattenGen(gen) } ?? []
    }
    
    func flatGen<S>(seq: S) -> [T] {
      return flattenGen(seq.generate())
    }
    
    func flatAr(ar: ArraySlice) -> ArraySlice {
      return ar.last.map {flatAr(dropLast(ar)) + ($0.map{[$0]} ?? [])} ?? []
    }
    
    func flatRec(var ar: [T?]) -> [T] {
        return ar.isEmpty ? [] : {flatRec(ar) + ($0.map {[$0]} ?? [])}(removeLast(&ar))
    }
    • Oh lord I will never understand how to properly format on websites.