我有一对像这样的对:
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},
]
我该怎么做?
答案 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}]