reduce e agregação
Outras formas de combinar elementos.
reduce e agregação é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
Da dobra à redução
Às vezes, você deseja combinar os elementos sem fornecer um valor de semente separado.
reduce usa o primeiro elemento como acumulador inicial e combina os demais com ele.
Ele é um parente mais enxuto de fold para casos em que o tipo dos elementos e o tipo do resultado são iguais.
Fundamentos de reduce
reduce recebe uma função binária (a, b) e a aplica à coleção, sem um valor inicial explícito.
Para uma soma, ele simplesmente adiciona todos os elementos.
val xs = List(1, 2, 3, 4)
val total = xs.reduce((a, b) => a + b)
@main def run(): Unit =
println(total) // 10A armadilha da coleção vazia
Como reduce não tem uma semente, chamá-lo em uma coleção vazia lança uma UnsupportedOperationException.
fold e foldLeft são seguros em coleções vazias porque usam como alternativa a semente fornecida.
Use reduce somente quando souber que a coleção não está vazia.
// List.empty[Int].reduce(_ + _)
// throws UnsupportedOperationException
List.empty[Int].foldLeft(0)(_ + _) // safe, returns 0reduceOption para obter segurança
reduceOption retorna um Option, fornecendo None para uma coleção vazia em vez de lançar uma exceção.
Essa é a forma segura de realizar uma redução quando a coleção pode estar vazia.
val xs = List(5, 9, 2)
val maybeMax = xs.reduceOption(_ max _)
@main def run(): Unit =
println(maybeMax) // Some(9)reduceLeft e reduceRight
Assim como fold, reduce tem variantes direcionais.
reduceLeft combina da esquerda para a direita; reduceRight, da direita para a esquerda. reduce simples não oferece garantia de ordem para coleções paralelas, portanto use a variante explícita quando a direção for importante.
val xs = List(1, 2, 3)
val l = xs.reduceLeft(_ - _) // (1-2)-3 = -4
val r = xs.reduceRight(_ - _) // 1-(2-3) = 2
@main def run(): Unit =
println((l, r)) // (-4, 2)Por que aggregate existe
fold e reduce exigem que os tipos do acumulador e dos elementos tenham uma relação simples.
aggregate é a forma mais geral de fold: permite que o acumulador tenha um tipo diferente AND informa ao Scala como unir acumuladores parciais, o que é importante para o processamento paralelo.
Assinatura de aggregate
aggregate recebe uma semente, uma seqop que dobra um elemento no acumulador e uma combop que une dois acumuladores.
Em uma coleção sequencial, combop raramente é usado; em uma coleção paralela, ele une os resultados de cada bloco.
val xs = List(1, 2, 3, 4)
val sum = xs.aggregate(0)(
(acc, x) => acc + x, // seqop
(a, b) => a + b // combop
)
@main def run(): Unit = println(sum) // 10aggregate com um tipo diferente
Aqui, aggregate dobra uma lista de palavras em um total único do tipo Int, correspondente ao comprimento.
seqop adiciona o comprimento de cada palavra, enquanto combop adiciona dois totais parciais.
O tipo do acumulador (Int) é diferente do tipo dos elementos (String).
val words = List("hi", "there", "you")
val chars = words.aggregate(0)(
(acc, w) => acc + w.length,
(a, b) => a + b
)
@main def run(): Unit = println(chars) // 10Agregação paralela
O verdadeiro poder de aggregate aparece com coleções paralelas.
Cada thread dobra seu próprio bloco com seqop; depois, os blocos são unidos com combop. As duas funções permitem que Scala divida e reúna o trabalho com segurança.
// Conceptual: par splits the work
// val n = data.par.aggregate(0)(_ + _.length, _ + _)
// seqop runs per chunk, combop merges chunk resultsEscolhendo a ferramenta certa
Use reduce ou reduceOption quando o tipo do resultado for igual ao tipo dos elementos e a combinação for associativa.
Use foldLeft quando precisar de uma semente ou de um tipo de resultado diferente em processamento sequencial.
Use aggregate quando os tipos do acumulador e dos elementos forem diferentes e você quiser uma combinação adequada ao processamento paralelo.
// reduce: same type, non-empty, associative
// foldLeft: seed + different type, sequential
// aggregate: different type + parallel mergeCombinando em uma única passagem
aggregate pode calcular várias coisas ao mesmo tempo acumulando os resultados em uma tupla.
Aqui, obtemos a soma e a contagem em uma única passagem, unindo as tuplas em combop.
val xs = List(2, 4, 6, 8)
val (s, c) = xs.aggregate((0, 0))(
(acc, x) => (acc._1 + x, acc._2 + 1),
(a, b) => (a._1 + b._1, a._2 + b._2)
)
@main def run(): Unit = println((s, c)) // (20, 4)Verificação rápida
Decida qual operação é mais segura para uma lista que pode estar vazia.
Recapitulação
A redução combina elementos sem um valor inicial, usando o primeiro elemento como início; ela lança uma exceção em uma coleção vazia, enquanto reduceOption retorna None.
aggregate é a dobra mais geral: um valor inicial, uma seqop para dobrar os elementos e uma combop para combinar acumuladores parciais em operações paralelas.
Escolha a redução para combinações associativas do mesmo tipo, foldLeft para dobras sequenciais com valor inicial e aggregate quando os tipos forem diferentes ou quando houver paralelismo.
Aprenda Scala com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 39
- Aulas
- 143
Perguntas Frequentes
A aula “reduce e agregação” é grátis?
Sim — o texto completo de “reduce e agregação” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “reduce e agregação”?
Outras formas de combinar elementos. Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “reduce e agregação”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Pensando recursivamente
- Padrões de acumuladores
- foldLeft e foldRight
- reduce e agregação