从复杂的哈希中提取数据



我有以下哈希:

def menu
  {
    diet: @diet,
    proteins: ["Tofurkey", "Hummus"],
    veggies: [:ginger_carrots, :potatoes, :yams],
    desserts: {
      pies: [:pumpkin_pie],
      other: ["Chocolate Moose"],
      molds: [:cranberry, :mango, :cherry]
    }
  }
end

我想从哈希中提取甜点,然后形成一个字符串,上面写着

"今晚我们有5种美味的甜点:南瓜派、巧克力驼鹿和3种模具:蔓越莓、芒果和樱桃。"

我有以下代码:

def whats_for_dessert
  "Tonight we have 5 delicious desserts:" +
    menu[:desserts][:pies].flatten.to_s +
    menu[:desserts][:other].to_s
end

该代码输出

"Tonight we have 5 delicious desserts:[:pumpkin_pie]["Chocolate Moose"]"

有没有更好的方法来收集数据,这样我就不会遇到一堆尴尬的角色?

看起来您收到了某种任务。练习使用结构糟糕的数据是很好的,因为每隔一段时间你就会使用别人的代码(你无法更改!),这些代码会输出非常尴尬的结构,比如你正在处理的结构。

您可以考虑编写如下方法:

def render_desserts(desserts_hash)
  message = "Tonight we have #{desserts_hash.values.flatten.size} delicious desserts: "
  msg_arry = desserts_hash.map do |key, array|
    if array.length > 1
      "#{array.length} #{key}: #{array.map(&:capitalize).join(' and ')}"
    else
      array[0].to_s.split(/[ _]/).map(&:capitalize).join(' ')
    end
  end
  msg_arry[-1] = "and " + msg_arry[-1]
  message += msg_arry.join(', ')
end

如果您运行,它会打印出您在原始作业中被要求打印的内容

puts render_desserts(menu[:desserts])

您可以这样做:

a = menu[:desserts].values.flatten
puts "Tonight we have #{a.size} delicious desserts: #{a.map(&:to_s).join(', ').gsub('_',' ')}."
  # => Tonight we have 5 delicious desserts: pumpkin pie, Chocolate Moose, cranberry, mango, cherry.

但是您不应该在散列值中混合数据类型。让他们所有的字符串,所有的产品的完整描述:

def menu
  { diet: @diet, proteins: ["Tofurkey", "Hummus"],
    veggies: [:ginger_carrots , :potatoes , :yams],
    desserts: ({
      :pies  => ["pumpkin pie"],
      :other => ["chocolate Moose"],
      :molds => ["cranberry mold", "mango mold", "cherry mold"]})}
end

然后将puts更改为:

puts "Tonight we have #{a.size} delicious desserts:n  #{a.join(', ')}."
=>  Tonight we have 5 delicious desserts:
=>    pumpkin pie, chocolate moose, cranberry mold, mango mold, cherry mold.

您需要甜点的数量:

dessert_count = menu[:desserts].values.flatten.size

然后(但从你的需求来看还不太清楚),你想从不同的列表中构建一个句子:

sentences = menu[:desserts].map { |kind, list|
  case list.size
  when 0 then ""
  when 1 then "#{list[0]}".titleize
  else        "#{list.size} #{kind.to_s.pluralize}: #{list.to_sentence.titleize}"
            #  3 molds: Cranberry, Mango and Cherry
  end
end

一旦你有了这个,你就可以构建你的最后一句话:

puts "Tonight we have #{dessert_count} delicious desserts: #{sentences.to_sentence}."

这是假设您有可用的active_support,它有非常有用的#to_sentence#titleize#pluralize方法。

最新更新