/ / Encontrando um objeto (s) dentro de um hash com um número específico usando Ruby - ruby-on-rails, ruby

Encontrar um objeto (s) dentro de um hash com um número específico usando Ruby - ruby-on-rails, ruby

Eu preciso criar um método que leva um hash e número como argumentos e retorna uma nova matriz de nomes de animal de estimação por idade.

my_family_pets_ages = {"Evi" => 6, "Hoobie" => 3, "George" => 12, "Bogart" => 4, "Poly" => 4,
"Annabelle" => 0, "Ditto" => 3}

Meu eu tenho duas soluções para o meu problema:

def my_hash_finding_method(source, thing_to_find)
source.select {|k,v| v.include? thing_to_find}
end
my_hash_finding_method(my_family_pets_ages, 3)

ou

def my_hash_finding_method(source, thing_to_find)
source.select {|k,v| v.has_value? thing_to_find}
end
my_hash_finding_method(my_family_pets_ages, 3)

Quando executo meu programa com o IRB ou a linha de comando, recebo:

my_solution.rb:15:in `block in my_hash_finding_method":
undefined method `include?"for 6:Fixnum (NoMethodError)

Porque é include? um método indefinido? Ele também diz a mesma coisa quando eu uso has_value? Eu poderia estar usando uma versão desatualizada do Ruby? Eu estou em 2.0.0?

ATUALIZAR: Esta é a nova solução que surgiu, parece funcionar.

def my_hash_finding_method(source, thing_to_find)
num_array = []
source.each do |k,v|
if v == thing_to_find
num_array << k
end
end
print num_array.sort
end

Respostas:

0 para resposta № 1

Eu vou ser um pouco tímido porque isso soa como lição de casa, mas você está ciente do que k e v representam nesse bloco?

A mensagem de erro é uma grande dica. Ele está lhe dizendo que você tentou enviar uma mensagem para algo que não é um hash, e, naturalmente, ele não tem os métodos definidos para Hashes. include? em um Fixnum.

(Verifica Documentação Ruby para Hash select para saber o que realmente está sendo colocado lá se você quiser saber mais.

Resumindo: dentro do bloco, você está trabalhando com variáveis ​​cujo valor é definido pelo Hash, não operando no próprio Hash. Você precisa verificar com base nelas.


0 para resposta № 2

Os dois métodos em questão não existem por padrão, pelo menos não para os objetos que você está usando.

v.include?

funcionaria se v era um Enumerable, como um hash ou uma matriz, mas em vez disso, é um valor numérico porque é o valor para essa chave específica e não tem esse método definido.

O mesmo é verdade para v.has_value?. v ainda é o valor para essa chave específica. select passa na chave e valor como parâmetros separados se você usar |k,v|. (No caminho do Ruby, eles seriam uma matriz de dois elementos se você usasse uma única variável).

Para ajudá-lo a aprender a ajudar a si mesmo, Ruby inclui o ri comando disponível na linha de comando. Você pode digitar ri has_value? para ver se isso é implementado por qualquer classe que Ri conhece. Entre outros resultados é:

=== Implementação deJogo da velha -------------------------------------------------- ---------------------------- hsh.has_value? (valor) -> verdadeiro ou falso  -------------------------------------------------- ----------------------------  Retorna true se o valor fornecido estiver presente para alguma chave em hsh.  h = {"a" => 100, "b" => 200} h.has_value? (100) # => verdadeiro h.has_value? (999) # => falso

Na mesma linha, por include?:

=== Implementação deJogo da velha -------------------------------------------------- ---------------------------- hsh.include? (chave) -> verdadeiro ou falso  -------------------------------------------------- ----------------------------  Retorna true se a chave dada estiver presente em hsh.  h = {"a" => 100, "b" => 200} h.has_key? ("a") # => true h.has_key? ("z") # => false

Em ambos os casos, um numérico não terá esses métodos, que é onde o erro está vindo.


Alguma coisa ao longo das linhas deste trabalho?

  def my_hash_finding_method(source, thing_to_find)
source.select {|k,v|
if v == thing_to_find then return source[k] end
}
end

Isso é próximo, mas return não pertence lá e resultará em apenas um valor, mesmo se houver vários valores existentes. Considere isto:

MY_FAMILY_PETS_AGES = {
"Evi"       => 6,
"Hoobie"    => 3,
"George"    => 12,
"Bogart"    => 4,
"Poly"      => 4,
"Annabelle" => 0,
"Ditto"     => 3
}

def my_hash_finding_method(source, thing_to_find)
source.select{ |k, v| v == thing_to_find }
end

my_hash_finding_method(MY_FAMILY_PETS_AGES, 3) # => {"Hoobie"=>3, "Ditto"=>3}

Se você deseja receber resultados classificados, bem, por quê? select nos Rubis atuais retornará um hash e hashesNão se beneficie da classificação, pois são basicamente objetos de acesso aleatório, o que resulta na capacidade de acessar valores com a mesma rapidez, independentemente de o hash estar classificado ou não classificado.

Se você quiser retornar uma matriz ordenada de pares de chave / valor, esta é uma maneira de fazer isso:

def my_hash_finding_method(source, thing_to_find)
source.select{ |k, v| v == thing_to_find }.sort_by{ |k, v| k }
end

my_hash_finding_method(MY_FAMILY_PETS_AGES, 3) # => [["Ditto", 3], ["Hoobie", 3]]

Se você quiser apenas os nomes dos animais de estimação, em vez de nome e idade, pegue apenas as chaves retornadas por select:

def my_hash_finding_method(source, thing_to_find)
source.select{ |k, v| v == thing_to_find }.keys.sort
end

my_hash_finding_method(MY_FAMILY_PETS_AGES, 3) # => ["Ditto", "Hoobie"]

Observe que na solução retornando um hash de select Estou a usar sort_bye um regular sort no último. sort é bom para valores como valores numéricos ecaracteres / strings que já têm uma ordem estabelecida, no entanto, é ineficiente ao classificar usando um bloco para acessar atributos dentro do valor passado, porque ele tem que fazer muita computação redundante para determinar como ordenar os valores de entrada. sort_by é um algoritmo interessante comumente conhecido como um Schwartzian Transform, que calcula o valor que está sendo classificado uma vez porentrada, lembra, classifica por esse valor, depois expõe os itens associados depois, na ordem correta. Isso resulta em uma classificação muito eficiente, que pode superar muito a classificação normal se o valor que está sendo classificado não estiver prontamente disponível.

Eu fiz benchmarks das diferenças e como executar rapidamente um tipo decrescente em "Classificando uma matriz em ordem decrescente em Ruby", então passe algum tempo olhando a resposta selecionada para essa pergunta.


0 para resposta № 3

Você está tentando agrupar por valor o hash?

Então tente:

pets.group_by{|k,v| v}

Se você está tentando retornar apenas a matriz de itens com um valor:

pets.map { |k, v| v == value }