数组ruby

时间:2016-02-23 18:31:53

标签: ruby

我有一对像这样的对:

arr = [
  {lat: 44.456, lng: 33.222}, 
  {lat: 42.456, lng: 31.222}, 
  {lat: 44.456, lng: 33.222}, 
  {lat: 44.456, lng: 33.222}, 
  {lat: 42.456, lng: 31.222}
]

某些地方有一些地理坐标。我希望得到一个数组,这些坐标按频率分组和排序。结果应如下所示:

[
  {h: {lat: 44.456, lng: 33.222}, fr: 3}, 
  {h: {lat: 42.456, lng: 31.222}, fr: 2},
]

我该怎么做?

3 个答案:

答案 0 :(得分:6)

解决此问题的标准方法是使用Enumerable#group_by或计数哈希。当其他人使用前者发布答案时,我会选择后者。

arr.each_with_object(Hash.new(0)) { |f,g| g[f] += 1 }.map { |k,v| { h: k, fr: v } }
  #=> [{:h=>{:lat=>44.456, :lng=>33.222}, :fr=>3},
  #    {:h=>{:lat=>42.456, :lng=>31.222}, :fr=>2}] 

首先,计算哈希的实例:

counts = arr.each_with_object(Hash.new(0)) { |f,g| g[f] += 1 }
  #=> {{:lat=>44.456, :lng=>33.222}=>3,
  #    {:lat=>42.456, :lng=>31.222}=>2}

然后构造哈希数组:

counts.map { |k,v| { h: k, fr: v } }
  #=> [{:h=>{:lat=>44.456, :lng=>33.222}, :fr=>3},
  #    {:h=>{:lat=>42.456, :lng=>31.222}, :fr=>2}] 

g = Hash.new(0)创建一个空哈希值,默认值为零。这意味着,如果g没有密钥k,则g[k]将返回零。 (哈希值不会改变。)g[k] += 1首先扩展为g[k] = g[k] + 1。如果g没有键k,则右侧的g[k]返回零,因此表达式变为: g[k] = 1

或者,你可以写:

counts = arr.each_with_object({}) { |f,g| g[f] = (g[f] ||= 0) + 1 }

如果你想要返回的数组的元素(哈希值)是:fr的值的递减顺序(这里它是巧合),请点击Enumerable#sort_by

arr.each_with_object(Hash.new(0)) { |f,g| g[f] += 1 }.
    map { |k,v| { h: k, fr: v } }.
    sort_by { |h| -h[:fr] }

答案 1 :(得分:4)

arr.group_by(&:itself).map{|k, v| {h: k, fr: v.length}}.sort_by{|h| h[:fr]}.reverse
# =>
# [
#   {:h=>{:lat=>44.456, :lng=>33.222}, :fr=>3},
#   {:h=>{:lat=>42.456, :lng=>31.222}, :fr=>2}
# ]

答案 2 :(得分:2)

arr.group_by{|i| i.hash}.map{|k, v| {h: v[0], fr: v.size}
#=> [{:h=>{:lat=>44.456, :lng=>33.222}, :fr=>3}, {:h=>{:lat=>42.456, :lng=>31.222}, :fr=>2}]