从复杂的哈希中提取数据

时间:2013-11-16 19:08:06

标签: ruby hash

我有以下哈希:

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\"]"

有没有更好的方法来收集数据,所以我最终不会遇到一堆尴尬的角色?

3 个答案:

答案 0 :(得分:1)

你可以这样做:

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.

答案 1 :(得分:1)

看起来你收到了某种作业。练习使用可怕的结构化数据是很好的,因为每隔一段时间你就会使用别人的代码(你无法改变!),这些代码输出的结构非常笨拙,就像你正在处理的那样。

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

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])

答案 2 :(得分:0)

你需要数量的甜点:

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方法。