Escrito por Reinder de Vries, em 9 de julho de 2020 em Desenvolvimento de aplicativos, o Swift

Mapa, Reduzir e Filtro de Swift

Em Swift você use map(), reduce() e filter() para fazer um loop através de coleções, como matrizes e dicionários, sem a utilização de um ciclo.

as funções map, reduce e filter vêm do reino da programação funcional (FP). Eles são chamados de funções de ordem superior, porque eles tomam funções como entrada. Você está aplicando uma função a uma matriz, por exemplo, para transformar seus dados.

as funções Map, Reduce e Filter do Swift podem ser desafiadoras para envolver sua cabeça. Especialmente se você sempre codificou loops for in para resolver problemas de iteração. Neste guia, você aprenderá como usar as funções map(_:), reduce(_:_:) e filter(_:) no Swift.

vamos começar!

  1. Introdução ao mapa, reduzir e filtrar
  2. Início Rápido: Funções de Ordem superior na Swift
  3. Usando a Função de Mapa
  4. Usando a Função de Reduzir
  5. Usando a Função de Filtro
  6. a Combinação de Mapa, Reduzir e Filtro
  7. Ler Mais

Introdução ao Mapa, Reduzir e Filtro

Quando você estiver a construção de apps para iOS, você normalmente usa processuais ou programação Orientada a Objeto. A programação funcional é diferente: ela lida apenas com funções. Sem variáveis, sem estado, sem for-loops-apenas funções.

a linguagem de programação Swift se presta perfeitamente para misturar programação funcional com abordagens não funcionais, como OOP. Você não precisa escrever estritamente código funcional, e adotar conceitos de programação funcional pode ajudá-lo a aprender a codificar melhor.

as funções map(_:), reduce(_:_:) e filter(_:) são chamadas de funções de ordem superior, porque assumem uma função como funções de entrada e retorno como saída. Tecnicamente, Swift retorna os resultados de uma operação (ou seja, uma matriz transformada) ao usar funções de ordem superior, enquanto uma linguagem funcional pura retornará uma coleção de funções. No Swift, as entradas para essas funções são fechamentos.

veja como eles funcionam:

  • a função map() aplica uma função a todos os itens de uma coleção. Pense em “mapear” ou transformar um conjunto de valores em outro conjunto de valores.
  • a função reduce() transforma uma coleção em um valor. Pense nisso como combinando muitos valores em um, como calcular a média de um conjunto de números.
  • a função filter() simplesmente retorna valores que passaram por uma instrução if-e somente se essa condição resultar em true.

caso você esteja pensando: “Olha, não preciso de programação funcional ou processamento de dados, porque meus aplicativos não fazem isso!”então não pare aqui. Em projetos de aplicativos recentes, usei mapear, reduzir e filtrar em várias ocasiões:

  • Filtragem de custos/receitas de valores com filter(_:), para atender a um limite, antes de mostrar os valores em um gráfico de linha,
  • Média de milhares de classificação de filmes em um valor com reduce(_:_:)
  • Mapeamento de algumas operações em uma seqüência de caracteres com hashtags, transformando-o em um normalizado coleção, com map(_:)

Você poderia ter resolvido todos esses problemas com um ciclo, mas você vai ver que o uso de map(), reduce() e filter() resulta em mais conciso, de fácil leitura e funcionais código.

Início Rápido: Funções de ordem superior em Swift

vamos nos concentrar em map(), reduce() e filter() neste tutorial. Antes de seguirmos em frente, aqui está uma visão geral rápida das funções de ordem superior mais comuns no Swift:

  • map(_:) loops sobre cada item em uma sequência, aplica-se uma função para cada elemento, e retorna a transformada resultado
  • reduce(_:_:) loops sobre cada item em uma seqüência, combina-los em um valor, e retorna o resultado combinado
  • filter(_:) loops sobre cada item em uma seqüência e retorna uma seqüência resultante que contém apenas itens que satisfazem uma dada função de filtragem
  • flatMap(_:) faz o mesmo que map(_:), exceto que ele achata a seqüência resultante, por exemplo, matrizes aninhadas são não-aninhados ou “achatada”
  • compactMap(_:) faz o mesmo que map(_:), exceto que ele remove nil valores da sequência resultante, antes de a devolver

Você pode usar essas funções em matrizes, dicionários, conjuntos, intervalos, sequências, e qualquer outro Swift tipo você pode iterar sobre. Se você quiser saber mais sobre compactMap(_:) e flatMap(_:), confira este tutorial.

vários tipos no Swift, como Array e Dictionary, têm funções que aceitam fechamentos como entrada. Espreitadela:

  • contains(where:) loops através de uma coleção, aplica-se um predicado (encerramento) para cada item, retorna um true se um item satisfaz o predicado, caso contrário,false
  • first(where:) loops através de uma coleção, aplica-se um predicado (encerramento) para cada item, e retorna o item se ele satisfaz o predicado
  • firstIndex(where:) faz o mesmo que first(where:), exceto que ele devolve o índice em vez do valor de

Você pode aprender mais sobre estas funções neste tutorial. Como where é usado no Swift também é interessante, você pode aprender mais sobre isso neste tutorial.

você viu as funções ” map ” e “reduce” no Swift escritas como map(_:) e reduce(_:_:) ao longo deste tutorial. Os sublinhados e dois pontos nessas funções fazem parte da assinatura da função, que é um formato especial para indicar os parâmetros da função. Por exemplo, a função map(_:) tem um parâmetro sem nome, enquanto a função reduce(_:_:) tem dois. Você pode aprender mais sobre isso neste tutorial: funções no Swift Explained.

contratado como um iOS developer

Aprender a construir o iOS 14 apps com Swift 5

Entrar para o meu curso de desenvolvimento iOS, e saiba como começar a sua carreira como um profissional de programadores de iOS.

usando a função Map

a função map(_:) loops sobre cada item em uma coleção e aplica uma operação a cada elemento da coleção. Ele retorna uma coleção de itens resultantes, aos quais a operação foi aplicada.

vejamos um exemplo. Temos uma variedade de temperaturas em Celsius que você deseja transformar em Fahrenheit.

você pode usar um loop for, como este:

let celsius = var fahrenheit: = for value in celsius { fahrenheit += }print(fahrenheit)// Output: 

o código funciona bem, mas é muito detalhado. Você precisa de uma variável mutável “helper” fahrenheit para armazenar as conversões calculadas enquanto trabalha com elas e precisa de 3 linhas de código para a própria conversão.

veja como podemos fazer o mesmo com o map(_:) função:

deixe celsius =
deixe fahrenheit = celsius.mapa { $0 * (9/5) + 32 }
de impressão(fahrenheit)
Ocultar avisos

Você pode até fazer tudo isso em uma linha:

.map {  * (9/5) + 32 }

o Que acontece aqui?

  1. uma constante celsius é definida, uma matriz de duplas e inicializada com alguns valores Celsius aleatórios.
  2. a função map(_:) é chamada na matriz celsius. A função tem um argumento, um fechamento, que converte de Celsius para Fahrenheit.
  3. finalmente, o resultado é impresso: a matriz convertida, de Celsius para Fahrenheit.

a função map(_:) transforma uma matriz em outra, aplicando uma função a cada item da matriz. O fechamento * (9/5) + 32 leva o valor de entrada em Celsius e retorna um valor em Fahrenheit. A matriz resultante de map(_:) é construída a partir desses valores convertidos.

vamos dar uma olhada mais de perto no fechamento. Se você já trabalhou com fechamentos antes, você reconhecerá a sintaxe de fechamento de mão curta. É uma maneira mais curta de codificar um encerramento, deixando de fora grande parte de sua sintaxe.

aqui está uma alternativa menos concisa:

let celsius = let fahrenheit = celsius.map({ (value: Double) -> Double in return value * (9/5) + 32})print(fahrenheit)

a chamada de função real map(_:) e seu fechamento, é esta:

··· = celsius.map({ (value: Double) -> Double in return value * (9/5) + 32})

o que se passa aí? A função map(_:) é chamada na matriz celsius. É preciso um argumento: um fechamento do tipo (Double) -> Double.

A primeira parte do encerramento, começando com {, indica que este encerramento tem um parâmetro value do tipo Double, e o encerramento retorna um valor do tipo Double. O corpo de fechamento, começando com return, simplesmente retorna o resultado do cálculo Celsius para Fahrenheit.

se você comparar a sintaxe de fechamento de mão curta com o código expandido acima, verá que:

  • os parênteses da função ( e ) são omitidos, porque você pode deixá-los fora quando o último parâmetro de uma chamada de função é um encerramento.
  • a parte () -> in pode ser omitida, porque o Swift pode inferir que você está usando um parâmetro Double como entrada e deve retornar um Double. Agora que você deixou de fora a variável value, você pode usar a mão curta .
  • a instrução return também pode ser deixada de fora, porque esse fechamento deve retornar o resultado de uma expressão de qualquer maneira.

mesmo que o exemplo de código acima use Double tipos, você não está limitado a esses tipos. O tipo resultante de uma função map() pode ter um tipo diferente do que você colocou nela, e você também pode usar map() em um Dictionary.

vamos passar para reduce(_:_:)!

usando a função de redução

os loops de função reduce(_:_:) sobre cada item em uma coleção e os reduz a um valor. Pense nisso como combinando vários valores em um.

a função de redução é talvez a mais difícil de mapear, reduzir, filtrar para compreender. Como você pode ir de uma coleção de valores para um valor?

alguns exemplos:

  • a Criação de uma soma de vários valores, por exemplo, 3 + 4 + 5 = 12
  • Concatenação de um conjunto de cadeias de caracteres, por exemplo, = "Zaphod, Trillian, Ford"
  • Média de um conjunto de valores, i.é.(7 + 3 + 10) / 3 = 7/3 + 3/3 + 10/3 = 6.667

Em processamento de dados, você pode imaginar muitas situações quando as operações simples como estes vêm a calhar. Como antes, você pode resolver qualquer um desses problemas com um loop for, mas reduce(_:_:) é simplesmente mais curto e rápido.

veja como:

vamos valores =
vamos soma = valores.reduzir(0, +)
print(soma)
Ocultar avisos

A função reduce(_:_:) tem dois argumentos, um valor inicial e um fechamento. No código acima, estamos fornecendo o operador +, que também é uma função com dois parâmetros.

você também pode fornecer seu próprio fechamento, é claro:

let valores =
let média = valores.reduzir (0.0) { $0 + $1 } / Duplo (valores.contagem)
print(média)
Ocultar avisos

No exemplo acima, você está calculando a média de três números. Os tipos de valores no código são todos Double. Estamos primeiro somando todos os números e, em seguida, dividi-los pela quantidade de números.

O reduce(_:_:) função é diferente de duas maneiras:

  1. O reduce(_:_:) função tem dois parâmetros sem nome; o valor inicial e o encerramento
  2. O encerramento, que é fornecido para reduce(_:_:) também tem dois parâmetros; o resultado atual da redução e o novo valor que está prestes a ser reduzido

aqui, confira isso:

vamos valores =
vamos soma = valores.reduzir(0) {
imprimir(“\($0) + \($1) = \($0 + $1)”)
retorno $0 + $1
}
de impressão(soma)
Ocultar avisos

No exemplo acima, você pode ver claramente e , a 2 parâmetros para o encerramento. Quando você executa o Código, esta é a saída que você obtém:

0 + 7 = 77 + 3 = 1010 + 10 = 2020

veja como estamos começando com 0e, em seguida, adicionando 7? Na próxima etapa, estamos tomando 7 – o valor de redução atual – e adicionamos 3, o valor “próximo” na redução.

aqui está outra maneira de olhar para ele:

0 + 7(0 + 7) + 3((0 + 7) + 3) + 10

isso também deixa claro por que você precisa de um valor inicial para reduce(_:_:), porque esse é o primeiro parâmetro do fechamento.

a redução pode ser complicada de entender. É importante entender que você está aplicando iterativamente uma operação, como +, a um conjunto de valores até ficar com apenas um valor. Você literalmente reduz a quantidade de valores.

vamos passar para filter(_:)!

usando a função de filtro

a função filter percorre todos os itens de uma coleção e retorna uma coleção contendo apenas itens que satisfazem uma condição de inclusão.

é como aplicar uma instrução ifa uma coleção e apenas manter os valores que passam pela condição.

aqui, confira isso:

let values =
let even = values.filtro {$0.émultiple (de: 2) }
impressão (mesmo)
ocultar avisos

no exemplo acima, você está filtrando números de values que são pares. A função isMultiple(of:) retorna true quando pode ser dividida por 2 e false caso contrário.

ao contrário de map(_:) e reduce(_:_:), O fechamento filter(_:) precisa retornar um booleano, então trueou false. Quando o encerramento retorna true, o valor é mantido e, quando false é retornado, o valor é omitido. É assim que filter(_:) filtra a matriz de entrada.

aqui está um exemplo um pouco mais claro, com o fechamento expandido:

let values = let even = values.filter({ (value:Int) -> Bool in return value.isMultiple(of: 2)})print(even) // Output: 

no exemplo, o encerramento retorna um valor booleano, indicado com -> Bool. É fornecido um parâmetro, o item na coleção, e retorna o resultado de isMultiple(of:). Limpo!

combinando Mapa, reduzir e filtrar

você pode combinar as funções map(), reduce() e filter()? Claro que pode!

digamos que temos uma classe de alunos. Você sabe o ano em que cada aluno nasceu. Você deseja calcular a idade combinada de todos os alunos nascidos em ou após 2000.

veja como você faz isso:

deixe agora = 2020
deixe anos =
deixe soma = anos.filtro({ $0 >= 2000 }).mapa ({agora – $0}).reduzir(0,+)
impressão (soma)
ocultar avisos

a amostra de código acima usa encadeamento. Ele usa o resultado de uma função como entrada para outra, combinando map-reduce-filter. A função map() é chamada na matriz de resultados da função filter() e a função reduce() é chamada no resultado da função map(). Da hora!

o código em si é simples:

  1. Faça uma constante now e years e atribua um monte de anos a ela.
  2. Filtre os anos abaixo de 2000, ou seja, manter aqueles para os quais >= 2000 é true
  3. Transformar cada ano de idade, subtraindo-se o ano de now
  4. Adicionar todas as idades, reduzindo com +

Vamos dar mais um exemplo interessante. Confira o código a seguir, retirado do tutorial sobre o FizzBuzz:

deixe fizzbuzz:(Int) -> String = { i
switch (i % 3 == 0, i % 5 == 0)
{
caso (true, false):
return “Fizz”
caso (false, true):
return “Buzz”
caso (true, true):
return “FizzBuzz”
padrão:
retorno ” \ (i)”
}
}
let result = Array(2…100).mapa (fizzbuzz).reduzir(“1”, { $0 + “, ” + $1 })
imprimir (resultado)
ocultar avisos

veja o que está acontecendo? Estamos transformando uma matriz com números de 2 a 100 em “Fizz”, “Buzz” ou “FizzBuzz” com map(_:), com base nas Regras do jogo. Finalmente, estamos reduzindo essa matriz de strings em uma grande string com reduce(_:_:), combinando todos os valores. Limpo!

Leitura Adicional

e se você tivesse que codificar tudo isso com for in loops? Você usaria muito mais código. E isso é o poder do map-reduce-filter: é mais conciso, muitas vezes mais fácil de ler e — admita — muito legal!

quer saber mais? Verifique estes recursos:

  • Como Usar “onde” Swift
  • FlatMap E CompactMap Explicado Na Swift
  • O melhor Guia para tampas de Swift
  • Como: Encontrar Um Item Em uma Matriz Na Swift
  • Jogar Com o Código: Pesquisa binária Em Swift
  • Começar com o Xcode Playgrounds

contratado como um iOS developer

Aprender a construir o iOS 14 apps com Swift 5

Entrar para o meu curso de desenvolvimento iOS, e saiba como começar a sua carreira como um profissional de programadores de iOS.

Deixe uma resposta

O seu endereço de email não será publicado.