Массивы Ruby: select (), collect () и map ()

107

Синтаксис отображения:

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

Вопрос, а если у меня есть:

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

Я хочу удалить каждую запись, которая имеет пустое значение qty в этом массиве, или выбрать только те, в которых есть какое-то значение.

Я попытался:

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

Просто возвращает много ложных, а затем, когда я использую то же самое, просто измените карту для выбора, я получаю:

[]
Ingalcala
источник
Если вы присмотритесь, похоже, что это массив хешей
Эмили
@ Эмили: Совершенно верно, я только что это понял. Последний пример кода заставил меня думать иначе, потому что :qtyтам даже не фигурирует.
Niklas B.

Ответы:

131

Похоже, detailsэто массив хешей. Итак, itemвнутри вашего блока будет весь хеш. Следовательно, чтобы проверить :qtyключ, вы должны сделать что-то вроде следующего:

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

Это даст вам все элементы, :qtyключ которых не является пустой строкой.

официальная документация по выбору

Эмили
источник
26

РЕДАКТИРОВАТЬ: я только что понял, что вы хотите отфильтровать detailsмассив хешей. В этом случае вы могли бы сделать

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

Сама внутренняя структура данных - это не массив, а хэш. Вы также можете использовать selectздесь, но в этом случае блоку присваиваются ключ и значение:

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

Или используя reject, что является обратным select(исключает все элементы, для которых выполняется данное условие):

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

Обратите внимание, что это Ruby 1.9. Если вам нужно поддерживать совместимость с 1.8, вы можете сделать:

Hash[h.reject { |key, value| value.empty? }]
Никлас Б.
источник
@ingalcala: Я только что понял, что мой ответ не совсем то, что вам нужно. Пожалуйста, проверьте мои изменения, чтобы узнать, как фильтровать сам detailsмассив.
Niklas B.
9

При работе с хешем {}используйте как ключ, так и значение блока внутри ||.

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

=>[false, false, true, false, false]
Майкл Берковски
источник