Menu
Coddy logo textTech

Higher-Order Personalizadas

Parte da seção Lógica e Fluxo do Journey de Swift da Coddy — lição 42 de 56.

Agora você pode escrever suas próprias funções de ordem superior e elas se encaixarão perfeitamente ao lado de map e filter. O formato é sempre o mesmo: receber um parâmetro de closure, chamá-lo dentro do loop e retornar o resultado.

extension Array {
    func myMap<T>(_ transform: (Element) -> T) -> [T] {
        var result: [T] = []
        for item in self {
            result.append(transform(item))
        }
        return result
    }
}

[1, 2, 3].myMap { $0 * 10 }       // [10, 20, 30]

Se extensões parecerem demais, escreva uma função livre em vez disso, a ideia é a mesma:

func count<T>(_ items: [T], where predicate: (T) -> Bool) -> Int {
    var n = 0
    for item in items where predicate(item) {
        n += 1
    }
    return n
}

Uma vez que você consegue passar closures, a biblioteca padrão deixa de parecer mágica e começa a parecer um conjunto de padrões que você mesmo poderia escrever.

challenge icon

Desafio

Médio

Escreva uma função livre partition(_ items: [Int], by predicate: (Int) -> Bool) -> ([Int], [Int]) que percorra o array uma vez e retorne uma tupla (matched, rest): elementos que satisfizeram o predicado e o restante, ambos na ordem original.

Leia duas linhas: um número inteiro min, e depois uma lista de inteiros separados por vírgula. Use sua função partition com um predicado que verifica n > min. Imprima:

  1. matched: <...>
  2. rest: <...>

Cada lista unida com , (ou vazia quando não houver nada para imprimir).

Para a entrada 5 / 2,7,3,8,5, a saída é:

matched: 7,8
rest: 2,3,5

Folha de consulta

Funções de ordem superior seguem um padrão consistente: aceitam um closure, chamam-no em um loop, retornam o resultado.

Como uma extensão:

extension Array {
    func myMap<T>(_ transform: (Element) -> T) -> [T] {
        var result: [T] = []
        for item in self {
            result.append(transform(item))
        }
        return result
    }
}
[1, 2, 3].myMap { $0 * 10 }  // [10, 20, 30]

Como uma função livre:

func count<T>(_ items: [T], where predicate: (T) -> Bool) -> Int {
    var n = 0
    for item in items where predicate(item) {
        n += 1
    }
    return n
}

Uma função partition que retorna uma tupla de elementos correspondentes e não correspondentes:

func partition(_ items: [Int], by predicate: (Int) -> Bool) -> ([Int], [Int]) {
    var matched: [Int] = []
    var rest: [Int] = []
    for item in items {
        if predicate(item) { matched.append(item) }
        else { rest.append(item) }
    }
    return (matched, rest)
}

Experimente você mesmo

let min = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }

// TODO: partition(_:by:) -> ([Int], [Int]); imprimir correspondentes e o restante
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Lógica e Fluxo