Carregando
Todos os artigos
Programação 18 min de leitura

Arrays em Ruby: Um Guia Visual e Prático

Aprenda arrays em Ruby de forma visual: criar e ler, acrescentar e tirar nas duas pontas, pilhas e filas, each, map, select e companhia, ordenar, combinar, arrays aninhados, as pegadinhas, uma medição real de Array vs. Set e exercícios com respostas.

nbkhope
Nesta página

Uma playlist, um carrinho de compras, a tabela de recordes, os jogadores de uma partida, as linhas de um arquivo: os programas estão cheios de listas. Em Ruby, uma lista é um Array, e os arrays do Ruby estão entre os mais amigáveis de qualquer linguagem. Eles crescem e encolhem sozinhos, guardam qualquer coisa que você colocar e vêm com um conjunto enorme de métodos para buscar, ordenar e transformar.

Neste guia você vai ver como um array é organizado, acrescentar e tirar elementos nas duas pontas, montar uma pilha e uma fila, encadear iteradores como map e select em pipelines arrumados, ordenar e combinar arrays, escapar de duas pegadinhas clássicas e medir quando um array é a ferramenta errada. Exercícios com respostas fecham o artigo.

Todas as saídas abaixo vêm de execuções reais com o Ruby 3.3. Os exemplos usam p, que mostra os arrays com os colchetes e as aspas.

Um nome, muitas caixas

Em vez de cinco variáveis separadas para cinco animais, um array guarda todos sob um só nome, em ordem:

Um array é uma prateleira numerada: um nome, muitas caixas. O array animais guarda "cão", "gato", "urso", "cavalo" e "águia" nos índices de 0 a 4, que também são de -5 a -1 contando a partir do fim. animais[1, 3] dá ["gato", "urso", "cavalo"]. animais.first é "cão", animais.last é "águia", animais.size é 5, e animais[10] é nil. Use fetch(10) se preferir receber um erro

Criando arrays

1animais = ["cão", "gato", "urso", "cavalo", "águia"]
2misturado = [12, "cão", 3.65, nil, true, [1, 2]]
3palavras = %w[maçã banana cereja]
4zeros = Array.new(3, 0)
5quadrados = Array.new(5) { |indice| indice * indice }
6digitos = (1..5).to_a
7
8p animais
9p misturado
10p palavras
11p zeros
12p quadrados
13p digitos
14p [].empty?
1["cão", "gato", "urso", "cavalo", "águia"]
2[12, "cão", 3.65, nil, true, [1, 2]]
3["maçã", "banana", "cereja"]
4[0, 0, 0]
5[0, 1, 4, 9, 16]
6[1, 2, 3, 4, 5]
7true
  • Colchetes com vírgulas são o jeito de sempre.
  • Um array do Ruby pode misturar qualquer tipo de valor, até outros arrays.
  • %w[...] é um atalho para um array de palavras soltas.
  • Array.new(5) { |indice| … } monta um array rodando o bloco uma vez por posição.

Lendo elementos

1animais = ["cão", "gato", "urso", "cavalo", "águia"]
2p animais[0]
3p animais[4]
4p animais[-1]
5p animais.first
6p animais.last(2)
7p animais[1, 3]
8p animais[1..3]
9p animais.size
10p animais[10]
11begin
12  animais.fetch(10)
13rescue IndexError => erro
14  puts "o fetch recusou: #{erro.message}"
15end
1"cão"
2"águia"
3"águia"
4"cão"
5["cavalo", "águia"]
6["gato", "urso", "cavalo"]
7["gato", "urso", "cavalo"]
85
9nil
10o fetch recusou: index 10 outside of array bounds: -5...5

A contagem começa no 0, então o último elemento fica em size - 1, ou simplesmente em -1. Pedir uma posição que não existe dá nil, em silêncio. Use o fetch quando um elemento faltando deve ser um erro.

Acrescentando e tirando elementos

Acrescentando e tirando nas duas pontas. Com o array "cão", "gato", "urso": unshift("dinossauro") acrescenta na frente, shift tira da frente, push("cavalo") acrescenta no fundo, e o << também, e pop tira do fundo. O pop e o shift devolvem o elemento que tiraram, para você usá-lo. O insert(indice, valor) e o delete_at(indice) funcionam em qualquer lugar do meio
1animais = ["cão", "gato", "urso"]
2
3animais.push("cavalo")
4animais << "águia"
5p animais
6
7tirado = animais.pop
8puts "o pop tirou #{tirado.inspect}"
9p animais
10
11animais.unshift("dinossauro")
12p animais
13
14primeiro = animais.shift
15puts "o shift tirou #{primeiro.inspect}"
16p animais
1["cão", "gato", "urso", "cavalo", "águia"]
2o pop tirou "águia"
3["cão", "gato", "urso", "cavalo"]
4["dinossauro", "cão", "gato", "urso", "cavalo"]
5o shift tirou "dinossauro"
6["cão", "gato", "urso", "cavalo"]

No meio

1animais = ["cão", "gato", "urso", "cavalo", "águia"]
2animais[1] = "tartaruga"
3p animais
4
5animais.insert(2, "coruja")
6p animais
7
8animais.delete("urso")
9p animais
10
11tirado = animais.delete_at(0)
12puts "o delete_at(0) tirou #{tirado.inspect}"
13p animais
1["cão", "tartaruga", "urso", "cavalo", "águia"]
2["cão", "tartaruga", "coruja", "urso", "cavalo", "águia"]
3["cão", "tartaruga", "coruja", "cavalo", "águia"]
4o delete_at(0) tirou "cão"
5["tartaruga", "coruja", "cavalo", "águia"]

O delete("urso") tira pelo valor (todas as cópias dele); o delete_at(0) tira pela posição.

Pilhas e filas

Esses quatro métodos das pontas transformam um array numa pilha ou numa fila prontas, dois dos padrões mais úteis da programação:

Dois jeitos clássicos de usar um array. Uma pilha: o último a entrar sai primeiro, usando push e pop, como um histórico de desfazer, em que a última mudança é desfeita primeiro. Uma fila: o primeiro a entrar sai primeiro, usando push e shift, como uma fila de impressão, em que o primeiro arquivo enviado sai primeiro
1# Uma pilha: o último a entrar é o primeiro a sair (como o desfazer)
2historico = []
3historico.push("digitar 'Olá'")
4historico.push("colocar negrito")
5historico.push("mudar a cor")
6puts "Desfazer: #{historico.pop}"
7puts "Desfazer: #{historico.pop}"
8p historico
9
10# Uma fila: o primeiro a entrar é o primeiro a sair (como a fila de uma loja)
11fila_de_impressao = []
12fila_de_impressao.push("relatorio.pdf")
13fila_de_impressao.push("foto.jpg")
14fila_de_impressao.push("ingresso.png")
15puts "Imprimindo: #{fila_de_impressao.shift}"
16puts "Imprimindo: #{fila_de_impressao.shift}"
17p fila_de_impressao
1Desfazer: mudar a cor
2Desfazer: colocar negrito
3["digitar 'Olá'"]
4Imprimindo: relatorio.pdf
5Imprimindo: foto.jpg
6["ingresso.png"]

Percorrendo um array

1animais = ["cão", "tartaruga", "urso"]
2
3animais.each { |animal| puts animal }
4
5animais.each_with_index do |animal, indice|
6  puts "#{indice + 1}. #{animal}"
7end
8
9indice = 0
10while indice < animais.length
11  puts animais[indice].upcase
12  indice += 1
13end
1cão
2tartaruga
3urso
41. cão
52. tartaruga
63. urso
7CÃO
8TARTARUGA
9URSO

O each entrega cada elemento, em ordem, ao bloco entre as chaves (ou entre do e end). O each_with_index acrescenta a posição. O laço while também funciona, mas em Ruby você quase sempre vai ver o each: não há índice para controlar e não tem como passar do fim.

A caixa de ferramentas dos iteradores: map, select e companhia

Além do each, os arrays têm iteradores que montam algo novo a partir dos elementos. Estes são os que você vai usar todo dia:

map, select, reject e find num relance, aplicados aos preços 12,5, 3,0, 45,0, 7,25, 19,99 e 2,5. map { preco * 1.1 } dá um array do mesmo tamanho com cada um mudado: 13,75, 3,3, 49,5, 7,98, 21,99, 2,75. select { preco > 10 } fica com os que batem: 12,5, 45,0, 19,99. reject { preco > 10 } joga fora os que batem: 3,0, 7,25, 2,5. find { preco > 10 } dá só o primeiro que bate: 12,5
1precos = [12.5, 3.0, 45.0, 7.25, 19.99, 2.5]
2
3p precos.map { |preco| (preco * 1.1).round(2) }
4p precos.select { |preco| preco > 10 }
5p precos.reject { |preco| preco > 10 }
6p precos.find { |preco| preco > 10 }
7p precos.count { |preco| preco < 5 }
8p precos.sum
9p precos.min
10p precos.max
11p precos.sum / precos.size
12p precos.reduce { |total, preco| total + preco }
1[13.75, 3.3, 49.5, 7.98, 21.99, 2.75]
2[12.5, 45.0, 19.99]
3[3.0, 7.25, 2.5]
412.5
52
690.24
72.5
845.0
915.04
1090.24
MétodoDevolvePense nele como
mapum array novo, do mesmo tamanho"transforme cada um em…"
selectos elementos que batem"fique com os que…"
rejectos elementos que não batem"jogue fora os que…"
findo primeiro que bate (ou nil)"ache um que…"
countquantos batem"quantos são…"
sum, min, maxum número"some / o menor / o maior"
reduceum valor montado passo a passo"combine todos em…"

Encadeando num pipeline

Como cada um deles devolve um array novo, dá para encadeá-los, um passo por linha:

Encadeando iteradores: filtrar, transformar, combinar. Quatro pedidos, café 3,50, bolo 4,25 não pago, sanduíche 7,00 e suco 4,00, passam por .select { pago }, que fica com café, sanduíche e suco; depois por .map { preço }, que dá 3,50, 7,00 e 4,00; depois por .sum, que dá 14,5. Cada passo entrega um array novo ao próximo, e o array de pedidos original nunca muda
1pedidos = [
2  { item: "café", preco: 3.5, pago: true },
3  { item: "bolo", preco: 4.25, pago: false },
4  { item: "sanduíche", preco: 7.0, pago: true },
5  { item: "suco", preco: 4.0, pago: true },
6]
7
8total_pago = pedidos
9  .select { |pedido| pedido[:pago] }
10  .map { |pedido| pedido[:preco] }
11  .sum
12
13puts "Pago até agora: #{total_pago}"
Pago até agora: 14.5

Cada pedido aqui é um hash. Arrays de hashes são o jeito de costume de um programa Ruby guardar uma lista de registros.

Ordenando, contando e agrupando

1notas = [72, 95, 88, 61, 95, 90]
2nomes = ["eva", "Bruno", "ana", "Davi"]
3
4p notas.sort
5p notas.sort.reverse
6p notas.sort { |primeira, segunda| segunda <=> primeira }
7p notas.uniq
8p notas.max(3)
9p nomes.sort
10p nomes.sort_by(&:downcase)
11p nomes.max_by(&:length)
12p notas.tally
13p notas.group_by { |nota| nota >= 90 ? "A" : "não A" }
1[61, 72, 88, 90, 95, 95]
2[95, 95, 90, 88, 72, 61]
3[95, 95, 90, 88, 72, 61]
4[72, 95, 88, 61, 90]
5[95, 95, 90]
6["Bruno", "Davi", "ana", "eva"]
7["ana", "Bruno", "Davi", "eva"]
8"Bruno"
9{72=>1, 95=>2, 88=>1, 61=>1, 90=>1}
10{"não A"=>[72, 88, 61], "A"=>[95, 95, 90]}
  • O sort puro coloca as maiúsculas antes das minúsculas ("Bruno" antes de "ana"). O sort_by(&:downcase) ordena do jeito que as pessoas esperam.
  • O <=> é o operador "nave espacial", que compara dois valores. Trocar os dois lados ordena ao contrário.
  • &:downcase é um atalho para { |nome| nome.downcase }.
  • O tally conta cada valor; o group_by separa os elementos em grupos.

Combinando arrays

Combinando arrays: +, -, & e |. Com meus guardando maçã, banana, cereja e seus guardando banana, cereja, tâmara: meus + seus dá tudo, com repetidos; meus - seus dá só o que está nos meus, maçã; meus & seus dá o que está nos dois, banana e cereja; e meus | seus dá o que está em qualquer um, sem repetidos: maçã, banana, cereja, tâmara
1meus = ["maçã", "banana", "cereja"]
2seus = ["banana", "cereja", "tâmara"]
3
4p meus + seus
5p meus - seus
6p meus & seus
7p meus | seus
8p [[1, 2], [3, [4, 5]]].flatten
9p ["Ana", "Bruno", "Carla"].zip([90, 85, 77])
10p (1..10).each_slice(3).to_a
11p [1, 2, 3, 4].each_cons(2).to_a
1["maçã", "banana", "cereja", "banana", "cereja", "tâmara"]
2["maçã"]
3["banana", "cereja"]
4["maçã", "banana", "cereja", "tâmara"]
5[1, 2, 3, 4, 5]
6[["Ana", 90], ["Bruno", 85], ["Carla", 77]]
7[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
8[[1, 2], [2, 3], [3, 4]]

O zip junta dois arrays em pares, como os dentes de um zíper; o each_slice(3) corta um array em grupos de 3; o each_cons(2) dá cada par de vizinhos.

Arrays dentro de arrays

Um array de arrays forma uma grade: linhas de colunas.

1tabuleiro = [
2  ["X", "O", "X"],
3  [" ", "X", "O"],
4  ["O", " ", "X"],
5]
6
7tabuleiro.each { |linha| puts linha.join(" | ") }
8p tabuleiro[1][2]
9p tabuleiro.map { |linha| linha[0] }
10p tabuleiro.transpose[0]
11diagonal = (0..2).map { |indice| tabuleiro[indice][indice] }
12puts "Diagonal: #{diagonal.join}"
13puts "O X venceu na diagonal!" if diagonal.all?("X")
1X | O | X
2  | X | O
3O |   | X
4"O"
5["X", " ", "O"]
6["X", " ", "O"]
7Diagonal: XXX
8O X venceu na diagonal!

tabuleiro[1][2] é a linha 1, coluna 2. O transpose troca linhas por colunas, então tabuleiro.transpose[0] é a primeira coluna.

Duas pegadinhas

Pegadinha 1: Array.new(3, []) divide um único array interno

Array.new(3, []) divide um único array interno. Com Array.new(3, []), as três casas apontam para o mesmo array, então grade[0] << "ops" aparece em todas as linhas. Com Array.new(3) { [] }, o bloco roda uma vez por casa, dando três arrays separados
1grade = Array.new(3, [])
2grade[0] << "ops"
3p grade
4
5grade_segura = Array.new(3) { [] }
6grade_segura[0] << "certo"
7p grade_segura
[["ops"], ["ops"], ["ops"]]
[["certo"], [], []]

O Array.new(3, []) cria um array vazio e coloca ele nas três casas. Mudá-lo por uma casa muda "todas", porque elas são o mesmo array. A forma com bloco roda uma vez por casa e cria um array novinho a cada vez. (Números, como em Array.new(3, 0), não têm problema, porque não dá para mudar um número no lugar.)

Pegadinha 2: métodos com ! mudam o original

1numeros = [3, 1, 2]
2ordenados = numeros.sort
3p numeros
4p ordenados
5
6numeros.sort!
7p numeros
8
9dobrados = numeros.map { |numero| numero * 2 }
10p dobrados
11numeros.map! { |numero| numero * 10 }
12p numeros
1[3, 1, 2]
2[1, 2, 3]
3[1, 2, 3]
4[2, 4, 6]
5[10, 20, 30]

sort, map, select, reverse e uniq devolvem um array novo; os gêmeos com ! (sort!, map!, select!…) mudam o array no lugar. Métodos como push, pop, << e delete mudam o array mesmo sem !.

Quando o array é a ferramenta errada: buscar

O include? responde "isto está na lista?":

1require "set"
2
3convidados = ["Ana", "Bruno", "Carla"]
4p convidados.include?("Bruno")
5p convidados.include?("Zeca")
6p convidados.index("Carla")
7
8lista_de_convidados = Set.new(convidados)
9p lista_de_convidados.include?("Bruno")
1true
2false
32
4true

Mas, para responder, um array precisa olhar os elementos um por um. Um Set (conjunto) é feito exatamente para essa pergunta: ele pula direto para a resposta. Medimos 10.000 verificações contra listas cada vez maiores:

Está na lista? Array vs. Set. 10.000 verificações com include?, metade encontrada e metade não, contra N nomes, medido para este artigo com Ruby 3.3.2 no Windows, mediana de 5 execuções, depois a mediana de 3 execuções do programa, em escala logarítmica. 100 nomes: Array 5,9 milissegundos, Set 0,8 milissegundo. 1.000 nomes: Array 57,5 milissegundos, Set 1,0 milissegundo. 10.000 nomes: Array 563,0 milissegundos, Set 1,7 milissegundo. 100.000 nomes: Array 11,5 segundos, Set 3,2 milissegundos. Um array confere os elementos um por um, então 10 vezes mais nomes quer dizer umas 10 vezes mais trabalho. Um Set pula direto para a resposta, quase na mesma velocidade para 100 nomes ou 100.000

Com 100.000 nomes, o array precisou de 11,5 segundos; o Set, de 3,2 milissegundos: umas 3.600 vezes mais rápido. Cada vez que a lista cresceu 10×, o tempo do array também cresceu umas 10×, enquanto o Set quase nem percebeu.

Um mapa dos métodos de array do dia a dia

Um mapa dos métodos de array do dia a dia. Criar: [1, 2, 3], %w[a b c], Array.new(3) com bloco, (1..5).to_a. Ler: [0] e [-1], first e last, [1, 3] e [1..3], size e empty?. Pôr e tirar: push e <<, pop, unshift e shift, insert e delete. Percorrer: each, each_with_index, each_slice, while. Transformar: map, select e reject, find, reduce. Medir: sum, min e max, count, tally. Ordenar: sort e sort_by, reverse, uniq, max_by. Combinar: + e -, & e |, zip, flatten

Hora de praticar

Tente fazer estes antes de espiar as respostas.

Exercício 1: Adivinhe a saída (aquecimento). O que isto imprime?

1fila = [1, 2, 3]
2fila.push(4)
3fila.shift
4fila.unshift(0)
5fila.pop
6p fila

Exercício 2: Carrinho de compras. Dado um carrinho de itens com preço e quantidade, imprima cada linha com o subtotal e depois o total.

Exercício 3: Repetidos. Uma lista de inscrições tem repetições: ["ana", "bruno", "ana", "carla", "bruno", "ana", "davi"]. Imprima a lista sem repetidos (mantendo a ordem original), quantos repetidos foram tirados e quais nomes se inscreveram mais de uma vez.

Exercício 4: Times. Separe 10 jogadores em times de 3 (o último time fica com quem sobrar) e imprima cada time com o seu número.

Exercício 5: Ranking. Dados pares de [nome, pontos], imprima os 3 melhores, do maior para o menor, com as suas posições.

Exercício 6: Gire uma figura (desafio). Uma figurinha está guardada como linhas de caracteres. Gire-a 90° para a direita. (Dica: pense no que o transpose faz e depois no que ainda fica de trás para a frente.)

Quiz rápido

  1. Qual é o índice do último elemento de um array de 5 elementos? Dê dois jeitos de escrevê-lo.
  2. Que dupla de métodos forma uma pilha, e qual forma uma fila?
  3. Qual é a diferença entre map e each?
  4. Por que o Array.new(3, []) surpreende as pessoas?
  5. Quando você deve usar um Set em vez de um array?

Respostas

Exercício 1: Passo a passo: [1, 2, 3, 4], depois o shift tira o 1, o unshift(0) coloca o 0 na frente e o pop tira o 4:

1fila = [1, 2, 3]
2fila.push(4)
3fila.shift
4fila.unshift(0)
5fila.pop
6p fila
[0, 2, 3]

Exercício 2: each para as linhas e sum com bloco para o total:

1carrinho = [
2  { item: "caderno", preco: 4.5, quantidade: 3 },
3  { item: "caneta", preco: 1.25, quantidade: 4 },
4  { item: "mochila", preco: 32.0, quantidade: 1 },
5]
6
7carrinho.each do |linha|
8  subtotal = linha[:preco] * linha[:quantidade]
9  puts "#{linha[:item].ljust(10)} #{linha[:quantidade]} x #{format('%5.2f', linha[:preco])} = #{format('%6.2f', subtotal)}"
10end
11total = carrinho.sum { |linha| linha[:preco] * linha[:quantidade] }
12puts "Total: #{format('%.2f', total)}"
1caderno    3 x  4.50 =  13.50
2caneta     4 x  1.25 =   5.00
3mochila    1 x 32.00 =  32.00
4Total: 50.50

Exercício 3: O uniq fica com a primeira cópia de cada nome, em ordem; o tally acha quem repetiu:

1inscricoes = ["ana", "bruno", "ana", "carla", "bruno", "ana", "davi"]
2sem_repetidos = inscricoes.uniq
3puts "Sem repetidos: #{sem_repetidos.inspect}"
4puts "Foram tirados #{inscricoes.size - sem_repetidos.size} repetidos"
5p inscricoes.tally.select { |nome, quantidade| quantidade > 1 }.keys
Sem repetidos: ["ana", "bruno", "carla", "davi"]
Foram tirados 3 repetidos
["ana", "bruno"]

Exercício 4: O each_slice(3) monta os grupos, e o with_index(1) os numera a partir do 1:

1jogadores = %w[Ana Bruno Carla Davi Eva Fabio Gabi Hugo Iris Joao]
2jogadores.each_slice(3).with_index(1) do |time, numero|
3  puts "Time #{numero}: #{time.join(', ')}"
4end
1Time 1: Ana, Bruno, Carla
2Time 2: Davi, Eva, Fabio
3Time 3: Gabi, Hugo, Iris
4Time 4: Joao

Exercício 5: Ordene pelos pontos negativos para os maiores virem primeiro, pegue 3 e desmonte cada par no bloco com (nome, pontos):

1pontuacoes = [["Ana", 1200], ["Bruno", 950], ["Carla", 1430], ["Davi", 800], ["Eva", 1310]]
2
3tres_melhores = pontuacoes.sort_by { |nome, pontos| -pontos }.first(3)
4tres_melhores.each_with_index do |(nome, pontos), indice|
5  puts "#{indice + 1}. #{nome.ljust(6)} #{pontos}"
6end
1. Carla  1430
2. Eva    1310
3. Ana    1200

Exercício 6: O transpose transforma colunas em linhas; inverter cada uma dessas linhas completa o giro para a direita:

1figura = [
2  ["#", ".", "."],
3  ["#", "#", "."],
4  ["#", "#", "#"],
5]
6
7girada = figura.transpose.map(&:reverse)
8
9puts "Antes:"
10figura.each { |linha| puts linha.join }
11puts "Depois de girar para a direita:"
12girada.each { |linha| puts linha.join }
1Antes:
2#..
3##.
4###
5Depois de girar para a direita:
6###
7##.
8#..

Quiz: (1) O índice 4, que dá para escrever como array[4], array[-1] ou array.last. (2) Uma pilha usa push + pop (o último a entrar sai primeiro); uma fila usa push + shift (o primeiro a entrar sai primeiro). (3) O each só visita os elementos e devolve o array original; o map monta e devolve um array novo com o que o bloco devolver. (4) Ele coloca o mesmo array em todas as casas, então mudar um muda todos; use Array.new(3) { [] }. (5) Quando a pergunta principal é "isto está aqui?", principalmente em listas grandes: no nosso teste, um Set respondeu umas 3.600 vezes mais rápido com 100.000 nomes.

Cola rápida

Eu quero…Escreva
Criar um array[1, 2, 3], %w[a b c], Array.new(3) { … }, (1..5).to_a
Ler um elementolista[0], lista[-1], lista.first, lista.last
Ler uma fatialista[1, 3], lista[1..3]
Contar elementoslista.size, lista.count { … }, lista.empty?
Pôr no fim / na frentelista.push(x) ou lista << x / lista.unshift(x)
Tirar do fim / da frentelista.pop / lista.shift
Pôr / tirar no meiolista.insert(2, x) / lista.delete(x), lista.delete_at(2)
Visitar cada elementolista.each { |item| … }, each_with_index
Transformar / filtrarmap { }, select { }, reject { }, find { }
Somar / extremossum, min, max, max_by { }
Ordenarsort, sort_by { }, reverse
Tirar repetidos / contar valoresuniq / tally
Combinar+, -, &, |, zip, flatten
Cortar em gruposeach_slice(3)
Conferir se algo está lá, rápidorequire "set" e depois Set.new(lista).include?(x)

Resumindo

Os arrays são a lista do dia a dia do Ruby, e eles fazem muita coisa:

  • Os índices começam no 0, índices negativos contam a partir do fim, e um índice que não existe dá nil (ou um erro com fetch).
  • push/pop e unshift/shift trabalham nas duas pontas, o que deixa pilhas e filas triviais.
  • O each visita; map, select, reject, find, sum e companhia calculam, e se encadeiam em pipelines legíveis.
  • sort, uniq, tally, group_by, zip e os operadores de conjunto respondem quase qualquer pergunta sobre uma lista numa linha só.
  • Cuidado com os valores compartilhados (Array.new(3) { [] }, não Array.new(3, [])) e com os métodos que mudam o array no lugar.
  • Para "está aqui?" em listas grandes, use um Set: umas 3.600 vezes mais rápido que um array com 100.000 nomes no nosso teste.

Para mais Ruby, leia O Que É a Linguagem de Programação Ruby?, Métodos de String em Ruby e Entrada e Saída de Arquivos em Ruby.

Obrigado pela leitura!

Conhece alguém que vai gostar? Mande para essa pessoa.

Mais artigos

Leia a seguir

Comentários

Seja gentil e específico. Comentários com links de contas novas aparecem depois da análise de um moderador.