Tengo una matriz [1,2,4,5,4,7] y quiero encontrar la frecuencia de cada número y guárdelo en un hash. Tengo este código, pero devuelve NoMethodError: undefined method '+' for nil:NilClass

def score( array )
  hash = {}
  array.each{|key| hash[key] += 1}
end

Salida deseada es

{1 => 1, 2 => 1, 4 => 2, 5 => 1, 7 => 1 }
  • señor, algunos sugieren el uso de inyectar (aka reducir), lo cual está bien, pero todo lo que tiene que hacer es cambiar hash = {} a hash = Hash.new(0). Que le dice a Rubí que si encuentra hash[key] en un contexto en el que debe de tener un valor (como hash[key] += 1 o v = hash[key]) y el hash no contiene la clave key, es para agregar key=>0 con el hash antes de tomar más acciones (tales como hash[key] += 1). Por otro lado, if hash[key] == 7 evaluará a if nil == 7 si key no está en el hash; key=>0 no será añadido a la hash.
  • Agradable la enseñanza…!! Gustó … +1.
  • el problema puede ser el mismo, pero no es la cuestión. Aquí, señor. quiere saber por qué fue un error en particular, que a mí me parece bastante ligit.
  • bueno, entonces digamos que es relacionado 🙂 stackoverflow.com/questions/9480852/array-to-hash-words-count
InformationsquelleAutor mr.musicman | 2013-11-13

8 Comentarios

  1. 15

    Hacer de la siguiente manera :

    def score( array )
      hash = Hash.new(0)
      array.each{|key| hash[key] += 1}
      hash
    end
    score([1,2,4,5,4,7]) # => {1=>1, 2=>1, 4=>2, 5=>1, 7=>1}

    O más Rubyish utilizando Enumerable#each_with_object:

    def score( array )
      array.each_with_object(Hash.new(0)){|key,hash| hash[key] += 1}
    end
    score([1,2,4,5,4,7]) # => {1=>1, 2=>1, 4=>2, 5=>1, 7=>1}

    La razón de por qué NoMethodError: undefined method '+' for nil:NilClass ?

    hash = {} es un espacio vacío,con el valor por defecto nil.nil es una instancia de Nilclass,y NilClass no tiene ningún método de instancia llamado #+. Así que usted tiene NoMethodError.

    Vistazo a la Hash::nuevo documentación :

    new  new_hash
    new(obj)  new_hash

    Devuelve un nuevo hash vacío. Si este hash posteriormente se accede mediante una clave que no corresponde a un hash de entrada, el valor devuelto depende del estilo de la nueva usada para crear el hash. En la primera forma, el acceso devuelve nil. Si obj es especificado, este solo objeto va a ser utilizado para todos los valores predeterminados. Si un bloque se especifica, será llamado con el objeto hash y la clave, y debe devolver el valor predeterminado. Es el bloque de la responsabilidad para almacenar el valor en el hash, si es necesario.

    • +1 para responder a la pregunta: «¿por Qué me sale este error?».
  2. 10

    Sólo el uso de la inyección. Este tipo de aplicación es exactamente lo que eso significa para el.
    Algo así como:

    a.inject(Hash.new(0)) {|hash,word| hash[word] += 1; hash }
  3. 10

    En Ruby 2.4+:

    def score(array)
      array.group_by(&:itself).transform_values!(&:size)
    end
  4. 2

    Amor me inyectar:

    results = array.inject(Hash.new(0)) {|hash, arr_element| hash[arr_element] += 1; hash }

    1.9.3p448 :082 > array = [1,2,4,5,4,7]
     => [1, 2, 4, 5, 4, 7] 
    1.9.3p448 :083 > results = array.inject(Hash.new(0)) {|hash, arr_element| hash[arr_element] += 1; hash }
     => {1=>1, 2=>1, 4=>2, 5=>1, 7=>1} 
    • Que (OMI) ser más limpio, con each_with_object: a.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
    • A cada uno lo suyo, @muistooshort 🙂
    • Yo tiendo a usar inject para «recorrer con comentarios de» situaciones y each_with_object para «recorrer y recoger» las situaciones. Me cansé de la ; hash cosas.
  5. 2

    Aquí hay una pequeña opción que utiliza el Hash de la matriz de inicializador

    Hash[arr.uniq.map {|v| [v, arr.count(v)] }]
    • Esto es O(n^2)…
  6. 1

    El punto aquí es que hash[1] no existe (nil) cuando se ve por primera vez 1 en la matriz.

    Necesita inicializar de alguna manera, y hash = Hash.new(0) es la manera más fácil. 0 es el valor inicial que desee en este caso.

  7. 1

    Ruby 2.7 en adelante tendrá la Enumerable#tally método que va a resolver esto.

    Del tronco documentación:

    Tallys la colección. Devuelve un hash, donde las claves son los elementos y los valores son números de elementos en la colección que corresponde a la clave.

    ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
  8. 0

    O utilizar el grupo por el método:

    arr = [1,2,4,5,4,7]
    
    Hash[arr.group_by{|x|x}.map{|num,arr| [num, arr.size] }]

Dejar respuesta

Please enter your comment!
Please enter your name here