No Conceito Vectors, dissemos que "arrays são o coração da linguagem Julia" e que um vetor é unidimensional.
Diante disso, seria razoável esperar que a linguagem ofereça muitas formas versáteis e poderosas de fazer coisas com vetores, seja lá o que isso signifique.
Algumas funções bem simples recebem um vetor como entrada e retornam um escalar.
v = [2, 3, 4]
length(v) # => 3
sum(v) # => 9
Suponha que você tenha um vetor numérico e queira subtrair 0.5 de cada valor.
julia> v = [1.2, 1.5, 1.7]
3-element Vector{Float64}:
1.2
1.5
1.7
julia> v - 0.5
ERROR: MethodError: no method matching -(::Vector{Float64}, ::Float64)
Isso falha, então que tal subtrair outro vetor?
julia> v - [0.5, 0.5, 0.5]
3-element Vector{Float64}:
0.7
1.0
1.2
Funciona, mas é bem tedioso e consome muita memória conforme os vetores ficam mais longos.
Felizmente, Julia tem um ponto "mágico" que resolve esse problema de forma bem simples: v .- 0.5 é tudo o que você precisa.
A próxima seção explica por quê.
Então, v - 0.5 falha, mas v .- 0.5 funciona, e precisamos entender o que o ponto está fazendo.
Duas coisas, que se combinam para dar o resultado desejado.
Primeiro, colocar um ponto antes de qualquer operador infixo significa "aplique esta operação a cada elemento separadamente".
Da mesma forma, colocar um ponto depois do nome de uma função a "vetoriza", mesmo que a função tenha sido escrita para entradas escalares.
julia> sqrt.([1, 4, 9])
3-element Vector{Float64}:
1.0
2.0
3.0
Vimos em um exemplo anterior que podemos subtrair vetores de mesmo comprimento, mas entenda que .- é um operador mais seguro que -, pois deixa clara a intenção de operar elemento a elemento.
julia> v .- [0.5, 0.5, 0.5]
3-element Vector{Float64}:
0.7
1.0
1.2
E quanto a vetores de comprimentos diferentes?
julia> v .- [0.5, 0.5]
ERROR: DimensionMismatch: arrays could not be broadcast to a common size
julia> v .- [0.5,]
3-element Vector{Float64}:
0.7
1.0
1.2
Em geral, comprimentos diferentes geram um erro, exceto quando um deles tem comprimento 1 (tecnicamente, uma dimensão "singleton").
Singletons como [0.5,] ou apenas 0.5 são expandidos automaticamente para o comprimento necessário por repetição.
É isso que está no coração do broadcasting.
Selecionar elementos de um vetor pelo número do índice já foi discutido em Conceitos anteriores.
a = collect('A':'Z') # => 26-element Vector{Char}
# index with an integer
a[2] # => 'B'
# index with a range
a[12:2:18] # => ['L', 'N', 'P, 'R']
# index with another vector
a[ [1, 3, 5] ] # => ['A', 'C', 'E']
Também é possível selecionar elementos que satisfazem alguma expressão lógica (tecnicamente, um "predicado"). Isso geralmente exige broadcasting.
julia> a[a .< 'D']
3-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
Para expressões mais complexas, os pontos tendem a se multiplicar (mas eles são pequenos e fáceis de digitar).
julia> a[a .< 'D' .|| a .> 'W']
6-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
'X': ASCII/Unicode U+0058 (category Lu: Letter, uppercase)
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'Z': ASCII/Unicode U+005A (category Lu: Letter, uppercase)
Uma lembrança de que o "vetor" pode, na verdade, ser qualquer iterável ordenado apropriado, como um intervalo:
julia> n = 3:10
3:10
julia> n[isodd.(n)]
4-element Vector{Int64}:
3
5
7
9
Você adora observar pássaros e acompanha quantos deles visitaram seu jardim nos últimos sete dias.
Você tem seis tarefas, todas sobre os números de pássaros que visitaram seu jardim.
Implemente a função today() para retornar quantos pássaros visitaram seu jardim hoje.
As contagens de pássaros estão ordenadas por dia, com o primeiro elemento sendo a contagem do dia mais antigo e o último elemento sendo a contagem de hoje.
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> today(birds_per_day)
1
Implemente a função increment_todays_count() para incrementar a contagem de hoje:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> increment_todays_count(birds_per_day)
[2, 5, 0, 7, 4, 2]
Implemente a função has_day_without_birds() que retorna true se houve um dia em que nenhum pássaro visitou o jardim; caso contrário, retorne false:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> has_day_without_birds(birds_per_day)
true
Implemente a função count_for_first_days() que retorna o número de pássaros que visitaram seu jardim desde o início da semana, mas limite a contagem ao número de dias especificado desde o início da semana.
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> count_for_first_days(birds_per_day, 4)
14
Alguns dias são mais movimentados que outros.
Um dia movimentado é aquele em que cinco ou mais pássaros visitaram seu jardim.
Implemente a função busy_days() para retornar o número de dias movimentados:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> busy_days(birds_per_day)
2
Você decide ampliar seus registros mantendo contagens de várias semanas. Em cada caso, as contagens estão organizadas por dia da semana, de segunda-feira como a primeira entrada a domingo como a última.
Implemente a função average_per_day() que retorna a média de 2 semanas.
julia> week1 = [7, 2, 9, 1, 3, 0, 10]
julia> week2 = [2, 6, 4, 1, 3, 8, 9]
julia> average_per_day(week1, week2)
[4.5, 4.0, 6.5, 1.0, 4.0, 3.0, 9.5]
Crie sua conta no Exercism para aprender e dominar Julia com 35 conceitos128 exercícios e mentoria humana de verdade, tudo de graça.