[ruby] Ruby Arrays: select(), collect(), and map()

The syntax for mapping:

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

Question how about if I have:

 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"}

I want to delete every entry which has an empty qty value on this array or select only the ones with some value in it.

I tried:

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

Just returns a lot of false and then when I use the same just change map to select I get:

[]

This question is related to ruby arrays

The answer is


It looks like details is an array of hashes. So item inside of your block will be the whole hash. Therefore, to check the :qty key, you'd do something like the following:

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

That will give you all items where the :qty key isn't an empty string.

official select documentation


When dealing with a hash {}, use both the key and value to the block inside the ||.

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

=>[false, false, true, false, false]

EDIT: I just realized you want to filter details, which is an array of hashes. In that case you could do

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

The inner data structure itself is not an Array, but a Hash. You can also use select here, but the block is given the key and value in this case:

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"}

Or using reject, which is the inverse of select (excludes all items for which the given condition holds):

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

Note that this is Ruby 1.9. If you have to maintain compatibility with 1.8, you could do:

Hash[h.reject { |key, value| value.empty? }]