Matrices de Ruby: select (), collect () y map ()

106

La sintaxis para el mapeo:

a = ["a", "b", "c", "d"]      #=> ["a", "b", "c", "d"] 
a.map {|item|"a" == item}     #=> [true, false, false, false] 
a.select {|item|"a" == item}  #=> ["a"]

Pregunta qué tal si tengo:

 irb(main):105:0> details[1]
 => {:sku=>"507772-B21", :desc=>"HP 1TB 3G SATA 7.2K RPM LFF (3 .", :qty=>"", 
 :qty2=>"1", :price=>"5,204.34 P"}

Quiero eliminar todas las entradas que tengan un valor de cantidad vacío en esta matriz o seleccionar solo las que tengan algún valor.

Lo intenté:

details.map {|item|"" == item}

Solo devuelve una gran cantidad de falsos y luego, cuando uso el mismo, simplemente cambio el mapa para seleccionar, obtengo:

[]
ingalcala
fuente
Si miras de cerca, parece que es una variedad de hashes
Emily
@Emily: Muy cierto, me acabo de dar cuenta. La última muestra de código me hizo pensar lo contrario, porque :qtyni siquiera aparece allí.
Niklas B.

Respuestas:

131

Parece que detailses una matriz de hashes. Entonces, itemdentro de su bloque estará todo el hash. Por lo tanto, para verificar la :qtyclave, haría algo como lo siguiente:

details.select{ |item| item[:qty] != "" }

Eso le dará todos los elementos donde la :qtyclave no es una cadena vacía.

documentación oficial seleccionada

Emily
fuente
26

EDITAR: Me acabo de dar cuenta de que quieres filtrar details, que es una matriz de hashes. En ese caso podrías hacer

details.reject { |item| item[:qty].empty? }

La estructura de datos interna en sí no es una matriz, sino un hash. También puede usar selectaquí, pero el bloque recibe la clave y el valor en este caso:

irb(main):001:0> h = {:sku=>"507772-B21", :desc=>"HP 1TB 3G SATA 7.2K RPM LFF (3 .", :qty=>"", :qty2=>"1", :price=>"5,204.34 P"}
irb(main):002:0> h.select { |key, value| !value.empty? }
=> {:sku=>"507772-B21", :desc=>"HP 1TB 3G SATA 7.2K RPM LFF (3 .", 
    :qty2=>"1", :price=>"5,204.34 P"}

O usando reject, que es el inverso de select(excluye todos los elementos para los que se cumple la condición dada):

h.reject { |key, value| value.empty? }

Tenga en cuenta que esto es Ruby 1.9. Si tiene que mantener la compatibilidad con 1.8, puede hacer:

Hash[h.reject { |key, value| value.empty? }]
Niklas B.
fuente
@ingalcala: Me acabo de dar cuenta de que mi respuesta no es realmente la que necesitas. Por favor, consulte mi edición para saber cómo filtrar la detailsmatriz en sí.
Niklas B.
9

Cuando se trata de un hash {}, utilice tanto la clave como el valor del bloque dentro del ||.

details.map {|key,item|"" == item}

=>[false, false, true, false, false]
Michael Berkowski
fuente