Dicas para jogar golfe em Ruby


62

Que dicas gerais você pode dar para jogar golfe em Ruby?

Estou procurando idéias que possam ser aplicadas para codificar problemas de golfe em geral específicos do Ruby. (Por exemplo, "Remover comentários" não seria uma resposta.)

Poste uma dica por resposta.


Alguém precisa escrever uma linguagem chamada Rub, que utiliza um único caractere Unicode para cada token de Ruby, um bocado como Jelly e Pyth :)
Mark Thomas

Respostas:


46
  • O números 100 e 126 pode ser escrita como ?da ?~em 1.8.
  • Em uma nota semelhante, se você precisar de uma cadeia de caracteres únicos em 1,9 x é menor que "x".
  • Se você precisar imprimir uma sequência sem acrescentar uma nova linha, $><<"string"é menor que print"string".
  • Se você precisar ler várias linhas de entrada, $<.map{|l|...}será menor que while l=gets;...;end. Além disso, você pode usar $<.readpara ler tudo de uma vez.
  • Se você deveria ler um arquivo $<e getso lerá em vez de stdin, se o nome do arquivo estiver ARGV. Assim, a maneira golfiest reimplementar catseria: $><<$<.read.

11
? x gera o código ascii em geral, para que você possa obter realisticamente todos os imprimíveis para dígitos em dois caracteres. 1.9 é diferente, 'a'.ord gera o número ascii, mas tem quatro bytes a mais que a versão decimal.
Hiato

8
Uma maneira ainda mais eficiente de implementar caté deixar o arquivo ruby ​​completamente vazio (0 bytes) e insistir para que ele seja executado na linha de comando com o -psinalizador.
Daniero 17/07/2013

11
ou, a partir da própria @ de daniero resposta ,puts *$<
Não que Charles

11
Então, no 1.8, tudo o que tenho a fazer é ir? ~ E ele retornará 126?
Simply Beautiful Art

5
Você pode ir além de 126 usando pensamentos como ou , ou se você é louco o suficiente:?﷽.ord=65021
Simply Beautiful Art

32

Use o operador splat para obter a cauda e a cabeça de uma matriz:

head, *tail = [1,2,3]
head => 1
tail => [2,3]

Isso também funciona da outra maneira:

*head, tail = [1,2,3]
head => [1,2]
tail => 3

Use o *método com uma string em uma matriz para unir elementos:

[1,2,3]*?,
=> "1,2,3"

27
  • Use abortpara finalizar o programa e imprimir uma sequência para STDERR - menor que o putsseguido porexit
  • Se você ler uma linha com gets, poderá ~/$/encontrar o comprimento (isso não conta uma nova linha à direita, se existir)
  • Use []para verificar se uma sequência contém outra:'foo'['f'] #=> 'f'
  • Use em trvez de gsubpara substituições em caracteres:'01011'.tr('01','AB') #=> 'ABABB'
  • Se você precisar remover as novas linhas à direita, use em chopvez dechomp

2
+1 para aborte~/$/
J -_- L

Por favor, explique como usar~/$/
Mathieu CAROFF

@MathieuCAROFF toda vez que você chama gets, seu resultado é armazenado na $_variável /regex/ ~= stringretorna o índice da primeira correspondência. Chamar ~um regex é equivalente a /regex/ ~= $_. Então seria algo comos=gets;l= ~/$/
Cyoce

20

Termine o seu end.

Tente remover enddo seu código.

Não use def...endpara definir funções. Faça um lambda com o operador new -> no Ruby 1.9. (O operador -> é um "stabby lambda" ou "dash rocket" .) Isso economiza 5 caracteres por função.

# 28 characters
def c n
/(\d)\1/=~n.to_s
end

# 23 characters, saves 5
c=->n{/(\d)\1/=~n.to_s}

As chamadas de método são c nou c(n). Chamadas Lambda são c[n]. Alterar cada um c npara c[n]custar 1 caractere; portanto, se você puder usar c nmais de 5 vezes, mantenha o método.

Todos os métodos que aceitam do...endblocos podem aceitar {...}blocos. Isso salva de 3 a 5 caracteres. Se a precedência de {...}for muito alta, use parênteses para corrigi-la.

# 48 characters
(?a..?m).zip (1..5).cycle do|a|puts a.join','end

# WRONG: passes block to cycle, not zip
(?a..?m).zip (1..5).cycle{|a|puts a.join','}

# 45 characters, saves 3
(?a..?m).zip((1..5).cycle){|a|puts a.join','}

Substitua if...else...endpelo operador ternário ?: . Se uma ramificação tiver duas ou mais instruções, coloque-as entre parênteses.

# 67 characters
if a<b
puts'statement 1'
puts'statement 2'else
puts'statement 3'end

# 62 characters, saves 5
a<b ?(puts'statement 1'
puts'statement 2'):(puts'statement 3')

Você provavelmente não possui whileou faz untilloops, mas se tiver, escreva-os no formato modificador.

(a+=1
b-=1)while a<b

Os parênteses são puts'statement 3'necessários?
Cyoce 2/12/16

15

Além de w0lf

Ao trabalhar com matrizes, .compactpode ser substituído por -[nil]para salvar 2 caracteres.

Combinado com acima -> você pode torná-lo ainda mais curto -[p]para salvar outros 2 caracteres.


14

Use as variáveis ​​pré-definidas curtas sempre que possível, por exemplo, em $*vez de ARGV. Há uma boa lista deles aqui , junto com muitas outras informações úteis.


12

Quando você estiver usando a interpolação de strings (como você deve ler na publicação de Martin Büttner ), você não precisará de colchetes se o seu objeto tiver um sigilo ( $, @) na frente. Útil para variáveis mágicas como $_, $&, $1etc:

puts "this program has read #$. lines of input"

Então, também, se você precisar imprimir uma variável mais do que a usa, poderá salvar alguns bytes.

a=42; puts "here is a: #{a}"; puts "here is a again: #{a}"
$b=43; puts "here is b: #$b"; puts "here is b again: #$b"

11

Se precisar descobrir se um elemento específico eestá dentro de um intervalo r, você pode usar

r===e

em vez de mais:

r.cover?(e) # only works if `r.exclude_end?` is false

ou

r.member?(e)

ou

r.include?(e)

3
Não é r===eainda mais curto?
akuhn

@akuhn Sim, é. Muito mais curto. Obrigado por apontar isso, ele me ajudou a encurtar o meu código de 10 caracteres, que é enorme: codegolf.stackexchange.com/a/6125/3527
Cristian Lupaşcu

11
De nada. Tudo o que pode ser usado em uma instrução switch foi ===implementado.
akuhn

10

$_ é a última linha de leitura.

  • print - se nenhum argumento fornecer conteúdo impresso de $_
  • ~/regexp/ - abreviatura de $_=~/regexp/

No Ruby 1.8, você tem quatro métodos para Kerneloperar $_:

  • chop
  • chomp
  • sub
  • gsub

No Ruby 1.9, esses quatro métodos existem apenas se o seu script usa -nor -p.

Se você deseja imprimir alguma variável frequentemente, use trace_var(:var_name){|a|p a}


2
Eles estão disponíveis apenas quando você executa o Ruby com a opção -pou -n. Referência.
Darren Pedra

11
Parece que trace_varsó funciona com $ variáveis globais
daniero

10

Use interpolação de string!

  1. Para substituir to_s. Se você precisar de parênteses em torno do que deseja transformar em uma sequência, terá to_sdois bytes a mais que a interpolação da sequência:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Para substituir a concatenação. Se você concatenar algo cercado por duas outras strings, a interpolação poderá economizar um byte:

    "foo"+c+"bar"
    "foo#{c}bar"
    

    Também funciona se a coisa do meio for concatenada, se você apenas mover a concatenação dentro da interpolação (em vez de usar várias interpolações):

    "foo"+c+d+e+"bar"
    "foo#{c+d+e}bar"
    

10

Evite lengthemif a.length<n

lengthé de 6 bytes, um pouco caro no código de golfe. em muitas situações, você pode verificar se a matriz possui alguma coisa em um determinado ponto. se você passar o último índice, obterá nilum valor falsey.

Então você pode mudar:

if a.length<5a if !a[4]para -5 bytes

ou

if a.length>5a if a[5]para -6 bytes

ou

if a.length<na if !a[n-1]para -3 bytes

ou

if a.length>na if a[n]para -6 bytes

Nota : funcionará apenas com uma matriz de todos os valores reais. ter nilou falsedentro da matriz pode causar problemas.


4
Eu sempre uso size... Mas isso é definitivamente melhor. BTW, funciona para Stringtambém.
Manatwork

10

Não use as palavras true- falsechave e .

Usar:

  • !ppor true(obrigado, histocrata!)
  • !0para false. Se tudo o que você precisa é de um valor falso, você pode simplesmente usar p(que retorna nil).

para salvar alguns caracteres.


11
A menos que você realmente precise true(ou seja, se um valor verdadeiro é suficiente, como em uma condição if), você nem precisa !!.
Martin Ender

4
E da mesma forma, p(que avalia nil) é um valor mais curto de falsey. O que significa que a maneira mais curta de obter trueé !p.
histocrat

@histocrat bom ponto! Eu editei minha resposta.
Cristian Lupascu 7/08/14


9

Se você precisar obter um número de ARGV, getou algo semelhante para fazer algo tantas vezes, em vez de chamá to_i-lo, basta usar ?1.upto x{do something x times}onde x é uma string.

Então, usar em ?1.upto(a){}vez de x.to_i.times{}economizará 2 caracteres.

Você também pode reescrever coisas como p 1 while 1ou p 1 if 1como p 1while 1oup 1if 1

Esse exemplo não é muito útil, mas pode ser usado para outras coisas.

Além disso, se você precisar atribuir o primeiro elemento de uma matriz a uma variável, a,=csalvará dois caracteres em vez dea=c[0]


9

Novos recursos no Ruby 2.3 e 2.4

É bom ficar a par dos novos recursos de idioma que ajudarão seu jogo de golfe. Existem alguns ótimos nos últimos Rubies.

Ruby 2.3

O operador de navegação segura: &.

Quando você chama um método que pode retornar, nilmas deseja encadear chamadas de método adicionais, caso contrário, desperdiça bytes manipulando o nilcaso:

arr = ["zero", "one", "two"]
x = arr[5].size
# => NoMethodError: undefined method `size' for nil:NilClass

x = arr[5].size rescue 0
# => 0

O "operador de navegação segura" interrompe a cadeia de chamadas de método se alguém retornar nile retornar nilpara toda a expressão:

x = arr[5]&.size || 0
# => 0

Array#dig & Hash#dig

Acesso profundo a elementos aninhados, com um belo nome abreviado:

o = { foo: [{ bar: ["baz", "qux"] }] }
o.dig(:foo, 0, :bar, 1) # => "qux"

Retorna nilse atingir um beco sem saída:

o.dig(:foo, 99, :bar, 1) # => nil

Enumerable#grep_v

O inverso de - Enumerable#grepretorna todos os elementos que não correspondem ao argumento fornecido (comparado com ===). Por exemplo grep, se um bloco é fornecido, seu resultado é retornado.

(1..10).grep_v 2..5 # => [1, 6, 7, 8, 9, 10]
(1..10).grep_v(2..5){|v|v*2} # => [2, 12, 14, 16, 18, 20]

Hash#to_proc

Retorna um Proc que gera o valor para a chave fornecida, o que pode ser bastante útil:

h = { N: 0, E: 1, S: 2, W: 3 }
%i[N N E S E S W].map(&h)
# => [0, 0, 1, 2, 1, 2, 3]

Ruby 2.4

O Ruby 2.4 ainda não saiu, mas em breve estará disponível e possui alguns ótimos recursos. (Quando for lançado, atualizarei esta postagem com alguns links para os documentos.) Aprendi sobre a maioria delas nesta excelente postagem no blog .

Enumerable#sum

Não mais arr.reduce(:+). Agora você pode apenas fazer arr.sum. É necessário um argumento opcional de valor inicial, cujo padrão é 0 para elementos numéricos ( [].sum == 0). Para outros tipos, você precisará fornecer um valor inicial. Também aceita um bloco que será aplicado a cada elemento antes da adição:

[[1, 10], [2, 20], [3, 30]].sum {|a,b| a + b }
# => 66

Integer#digits

Isso retorna uma matriz de dígitos de um número na ordem do menor para o maior:

123.digits # => [3, 2, 1]

Comparado com, digamos 123.to_s.chars.map(&:to_i).reverse, isso é muito bom.

Como bônus, é necessário um argumento radix opcional:

a = 0x7b.digits(16) # => [11, 7]
a.map{|d|"%x"%d} # => ["b", "7"]

Comparable#clamp

Faz o que diz na lata:

v = 15
v.clamp(10, 20) # => 15
v.clamp(0, 10) # => 10
v.clamp(20, 30) # => 20

Como está no Comparable, você pode usá-lo com qualquer classe que inclua Comparable, por exemplo:

?~.clamp(?A, ?Z) # => "Z"

String#unpack1

Economia de 2 bytes em relação a .unpack(...)[0]:

"👻💩".unpack(?U)    # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U)   # => 128123

Argumento de precisão para Numeric#ceil, flooretruncate

Math::E.ceil(1) # => 2.8
Math::E.floor(1) # => 2.7
(-Math::E).truncate(1) # => -2.7

Atribuição múltipla em condicionais

Isso gera um erro nas versões anteriores do Ruby, mas é permitido na 2.4.

(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"

Golfe Math::E.ceil(1)para Math::E.ceil 1, e da mesma forma para floore truncate.
Simply Beautiful Art

11
@SimplyBeautifulArt Espero que alguém que pratique golfe em Ruby possa dar esse salto por conta própria.
Jordânia

Pois Enumerable#sum, .flatten.sumé 2 bytes menor que.sum{|a,b|a+b}
Asone Tuhid

(-Math::E).truncate(1)é equivalente ao -Math::E.truncate(1)que é 1 byte mais curto
Asone Tuhid

11
&.pode ser usado com subscrições como essa a&.[]i(1 byte menor que a&.at i). Embora, se forem necessários colchetes, a||a[i]1 byte é menor que a&.[](i)oua&.at(i)
Asone Tuhid 1/18/18

7

A notação científica geralmente pode ser usada para cortar um ou dois caracteres:

x=1000
#versus
x=1e3

9
Nota: Isso retornará um valor flutuante (1000.0) em vez de um número inteiro, o que pode causar resultados imprecisos com números grandes.
Dogbert

4
Ah, legal 1e2é melhor do que 100.0quando uma porcentagem é necessária.
Phrogz

Semelhante a esse princípio, 1.0*é 1 caractere mais curto que.to_f
Unihedron

7

Use métodos de operador em vez de parênteses

Digamos que você queira se expressar a*(b+c). Por causa da precedência, a*b+cnão funcionará (obviamente). A maneira legal de Ruby de ter operadores como métodos vem em socorro! Você pode usar a.*b+cpara tornar a precedência *menor que a de +.

a*(b+c) # too long
a*b+c   # wrong
a.*b+c  # 1 byte saved!

Isso também pode funcionar com os operadores !e ~(coisas como unárias +ou unárias -não funcionam porque seus métodos são -@e +@, salvando ()mas adicionando .@)

(~x).to_s # too long
~x.to_s   # error
x.~.to_s  # 1 byte saved!

6

Use ||em vez disso ore &&em vez disso and.

Ao lado de um caractere, andvocê pode salvar os espaços (e talvez o suporte) ao redor do operador.

p true and false ? 'yes' :'no'   #-> true (wrong result)
p (true and false) ? 'yes' :'no' #-> 'no'
p true&&false ? 'yes' :'no'      #-> 'no', saved 5 characters


p true or false ? 'yes' :'no'   #-> true (wrong result)
p (true or false) ? 'yes' :'no' #-> 'yes'
p true||false ? 'yes' :'no'      #-> 'yes', saved 4 characters

Se você faz um loop em uma matriz, você normalmente usa each. Mas maptambém faz um loop em uma matriz e é um caractere mais curto.


6

Eu apenas tentei um desafio de código-golfe no TDD, ou seja, escreva o código mais curto para fazer as especificações passarem. As especificações eram algo como

describe PigLatin do
  describe '.translate' do
    it 'translates "cat" to "atcay"' do
      expect(PigLatin.translate('cat')).to eq('atcay')
    end
    # And similar examples for .translate
  end
end

Por uma questão de código-golfe, não é necessário criar um módulo ou classe.

Ao invés de

module PigLatin def self.translate s;'some code'end;end

alguém pode fazer

def(PigLatin=p).translate s;'some code'end

Salva 13 caracteres!


7
Ha, muito completo. Não só você adicionar o comportamento necessário PigLatin, mas também para @pig_latin, $pig_latin, e 'pig'['latin'].
histocrat 27/02

@histocrat: Agora entendi. É porque translatefoi definido em nil.
precisa

6

O kernel # p é um método divertido.

Use em p varvez de puts var. Isso funciona perfeitamente com números inteiros e flutuantes, mas não com todos os tipos. Ele imprime aspas em torno de strings, o que provavelmente não é o que você deseja.

Usado com um único argumento, pretorna o argumento após imprimi-lo.

Usado com vários argumentos, pretorna os argumentos em uma matriz.

Use p(sem argumentos) em vez de nil.


10
Infelizmente, p 'some string'imprime "some string"e não apenas o some stringque é frequentemente criticado por outros.
Patrick Oscity

11
Basicamente, p sé o mesmo que puts s.inspect, mas ele retornas
Cyoce 3/16

6

Não use #each. Você pode fazer um loop sobre todos os elementos muito bem com #map. Então, ao invés de

ARGV.each{|x|puts x}

você pode fazer o mesmo em menos bytes.

ARGV.map{|x|puts x}

Obviamente, nesse caso, puts $*seria ainda mais curto.


Existem literais para números racionais e complexos:

puts 3/11r == Rational(3,11)
puts 3.3r == Rational(66,20)
puts 1-1.i == Complex(1,-1)

=> true
true
true

Você pode usar a maioria dos bytes dentro de strings. "\x01"(6 bytes) pode ser reduzido para ""(3 bytes). Se você precisar apenas desse byte, ele poderá ser reduzido ainda mais para ?(2 bytes).

Da mesma forma, você pode obter novas linhas mais curtas assim:

(0..10).to_a.join'
'

 => "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"

Você pode usar ?\ne ?\tbem, que é um byte menor do que "\n"e "\t". Para ofuscação, também há um espaço.


Use constantes em vez de passar argumentos, mesmo que precise alterá-los. O intérprete dará avisos ao stderr , mas quem se importa. Se você precisar definir mais variáveis ​​relacionadas entre si, poderá encadeá-las da seguinte maneira:

A=C+B=7+C=9

=> A=17, B=16, C=9

Isso é mais curto que C=9;B=16;A=17ou C=0;B=C+7;A=C+B.


Se você precisar de um loop infinito, use loop{...}. Loops de comprimento desconhecido podem ser mais curtos com outros loops:

loop{break if'
'==f(gets)}

while'
'!=f(gets);end

Mais alguns truques gsub / regexp. Use os '\1'caracteres de escape especiais em vez de um bloco:

"golf=great short=awesome".gsub(/(\w+)=(\w+)/,'(\1~>\2)')

"golf=great short=awesome".gsub(/(\w+)=(\w+)/){"(#{$1}~>#{$2})")

E as variáveis ​​especiais $1etc., se você precisar executar operações. Lembre-se de que eles são definidos não apenas dentro do bloco:

"A code-golf challenge." =~ /(\w+)-(\w+)/
p [$1,$2,$`,$']

=> ["code", "golf", "A ", " challenge."] 

Livre-se de espaços, novas linhas e parênteses. Você pode omitir um pouco o rubi. Em caso de dúvida, tente sempre se funciona sem problemas e lembre-se de que isso pode interromper a sintaxe de alguns editores que destacam ...

x+=1if$*<<A==????::??==??

"Por favor, poste uma dica por resposta." Também ?\né legal, mas não muito mais curto do que realmente colocar um caractere de nova linha entre aspas. (mesmo para guia)
Martin Ender

E puts$*é ainda mais curto.
precisa saber é o seguinte

Eu sei que você estava tentando provar um ponto, mas tenho certeza de que o último exemplo é o mesmo quex+=1;$*<<A
Asone Tuhid

6

Ainda outra maneira de usar o operador splat: se você deseja atribuir uma única matriz literal, a *no lado esquerdo é mais curta que os colchetes no lado direito:

a=[0]
*a=0

Com vários valores, você nem precisa do operador splat (obrigado ao histocrat por me corrigir nisso):

a=[1,2]
a=1,2

O último caso não precisa realmente do splat.
histocrat

@histocrat Oh uau, eu pensei que o segundo valor seria descartado nesse caso.
Martin Ender

11
Não acredito que não as conheço o tempo todo em que passei jogando golfe em Ruby.
Maçaneta

6

Quando um desafio exige que você produza várias linhas, você não precisa repetir os resultados para imprimir cada linha, por exemplo, uma matriz. O putsmétodo achatará uma matriz e imprimirá cada elemento em uma linha separada.

> a = %w(testing one two three)
> puts a
testing
one
two
three

A combinação do operador splat com #pvocê pode torná-lo ainda mais curto:

p *a

O operador splat (tecnicamente, o *@método, eu acho) também lança seus enumeráveis ​​não array para matrizes:

> p a.lazy.map{|x|x*2}
#<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>

vs

> p *a.lazy.map{|x|x*2}
2
4
6

11
*@não é um método, splat é açúcar sintático
Asone Tuhid

6

Salve alguns bytes ao remover elementos repetidos de uma matriz

a.uniq # before
a|[]   # after
    ^^

Se você estiver usando uma matriz vazia []em uma variável, poderá salvar ainda mais bytes:

a.uniq;b=[] # before
a|b=[]      # after
      ^^^^^

2
Para o primeiro caso, a&aé 1 byte mais curto
Asone Tuhid 7/18

5

Use Goruby em vez de Ruby, que é algo como uma versão abreviada do Ruby. Você pode instalá-lo com o rvm via

rvm install goruby

O Goruby permite que você escreva a maior parte do seu código como escreveria Ruby, mas possui abreviações adicionais. Para descobrir a abreviação mais curta disponível para algo, você pode usar o método auxiliar shortest_abbreviation, por exemplo:

shortest_abbreviation :puts
#=> "pts"

Array.new.shortest_abbreviation :map
#=> "m"

String.new.shortest_abbreviation :capitalize
#=> "cp"

Array.new.shortest_abbreviation :join
#=> "j"

Também é muito útil o alias saypara o putsqual ele próprio pode ser abreviado s. Então, ao invés de

puts [*?a..?z].map(&:capitalize).join

agora você pode escrever

s [*?a..?z].m(&:cp).j

para imprimir o alfabeto em maiúsculas (o que não é um bom exemplo). Esta postagem do blog explica mais coisas e alguns dos trabalhos internos, se você estiver interessado em ler mais.

PS: não perca o hmétodo ;-)


Mais de 2 anos depois e eu finalmente descobri o que esta resposta me lembra ...
undergroundmonorail

5

Para ingressar em uma matriz, em vez desta

[...].join

fazem isto

[...]*''

que economiza 2 bytes. Para ingressar em um separador, use

[...]*?,

5

Números de assinatura!

Acabei de descobrir isso ontem. n[i]retorna no bit na iposição-th. Exemplo:

irb(main):001:0> n = 0b11010010
=> 210
irb(main):002:0> n[0]
=> 0
irb(main):003:0> n[1]
=> 1
irb(main):004:0> n[2]
=> 0
irb(main):005:0> n[3]
=> 0
irb(main):006:0> n[4]
=> 1
irb(main):007:0> n[5]
=> 0

E agora você pode usar mais argumentos comon[0..3]
Simply Beautiful Art

4

Você pode salvar 2 caracteres e usar

[*(...)]

ao invés de

(...).to_a

Por exemplo, suponha que tenhamos um intervalo que queremos como uma matriz:

(1..2000).to_a

Apenas faça assim:

[*1..2000]  #  Parentheses around the (ran..ge) is not needed!

E agora você tem seu alcance como uma matriz.


5
Eu acho que [*1..2000]funciona também?
Lynn

4

<< truque

a.push x

pode ser reduzido para:

a<<x

para -4 bytes.


2
Nota: isso também funciona para Strings
Cyoce 4/16

4

Array#assoc/rassoc

Quando você tem uma matriz de matrizes e deseja encontrar a sub-matriz que começa com um valor específico, não use Enumerable#find, use Array#assoc:

a = [[0,"foo"],[0,"bar"],[1,"baz"],[0,"qux"]]
a.find{|x,|x==1} # => [1,"baz"]
a.assoc(1) # => [1,"baz"]

Este também é um bom substituto para Enumerable#any?em algumas situações.

Array#rassoc faz a mesma coisa, mas verifica o último elemento das sub-matrizes:

a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil

Para a a.any?linha do rassoc exemplo, o que |x,|faz? Qual é a diferença |x|?
Cyoce 4/11/16

@Cyoce Bloco parâmetro desestruturação segue as mesmas regras que desestruturação atribuição, por isso é como x=[1,2]vs x,=[1,2]. Usando o meu exemplo acima, com |x|, na primeira iteração xserá [0,"foo"]. Com |x,y|, xserá 0e yserá "foo". Da mesma forma, com |x,|, xserá 0. Em outras palavras, ele diz que "colocar o primeiro elemento xe jogar o resto fora.
Jordan

Observe que ele não funciona ao contrário, por exemplo, |,y|é um SyntaxError, ergo |_,y|. Mas agora percebi que |*,y|funciona, o que é mais limpo do que usar uma variável chamada _(mas não menor).
Jordan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.