2011-08-02 98 views
0

我有获取嵌套元素的频率,与关系保留

  • 商店对象数组

    • 属于城市对象

      • 属于县对象

我想通过县,然后城市,那么频率上市的哈希落得...

我想出了这一点,但感觉真的未rubylike ..

city_by_prefecture = shop_list.reduce({}){ |h,e| 
    if h[e.prefecture.name].nil? 
    h[e.prefecture.name] = {e.city.name => 1} 
    elsif h[e.prefecture.name][e.city.name].nil? 
    h[e.prefecture.name][e.city.name] = 1 
    else 
    h[e.prefecture.name][e.city.name] += 1 
    end 
    h 
} 

必须有DRY-er的方式来做到这一点!

+0

可能重复的[如何分配散列\ [ “一” \] \ [ “b” 的\] = “C”,如果散列\ [ “一” \]不存在?] (http://stackoverflow.com/questions/5878529/how-to-assign-hashab-c-if-hasha-doesnt-exist) –

+1

你可能想使用'h.has_key?(e.prefecture.name)'而不是'h [e.prefecture.name] .nil?',因为这样你的问题就更加明显了。另外,使用'each_with_object'而不是'reduce',所以你不必在块的末尾加上'h'。 –

+0

谢谢安德鲁。我不知道'each_with_object'。 – minikomi

回答

1
city_by_prefecture = shop_list.each_with_object({}){ |e,h| 
    h[e.prefecture.name] ||= Hash.new(0) 
    h[e.prefecture.name][e.city.name] += 1 
} 
+0

更清洁!谢谢。 – minikomi

0
shops = [ 
    OpenStruct.new(:prefacture => "pre1", :city => "city1"), 
    OpenStruct.new(:prefacture => "pre1", :city => "city1"), 
    OpenStruct.new(:prefacture => "pre1", :city => "city2"), 
    OpenStruct.new(:prefacture => "pre2", :city => "city3"), 
] 

counts = Hash[shops.group_by(&:prefacture).map do |prefacture, shops_in_prefacture| 
    [prefacture, Hash[shops_in_prefacture.group_by(&:city).map do |city, shops_in_city| 
    [city, shops_in_city.size] 
    end]] 
end] 
# {"pre1"=>{"city1"=>2, "city2"=>1}, "pre2"=>{"city3"=>1}}