Ruby 数组中对的频率
我有一个这样的成对数组:Ruby 数组中对的频率,ruby,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.
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},
]
有些地方有一些地理坐标。我想得到一个数组,用这些坐标按频率分组和排序。结果应该如下所示:
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},
]
我如何才能做到这一点?处理此问题的标准方法是使用或使用计数哈希。由于其他人使用前者发布了答案,我将使用后者
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}
# ]
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.new0创建一个默认值为零的空哈希。这意味着如果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值的降序排列,那么这是巧合,请附加:
处理此问题的标准方法是使用或计数哈希。由于其他人使用前者发布了答案,我将使用后者
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.new0创建一个默认值为零的空哈希。这意味着如果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值的降序排列,那么这是巧合,请附加:
为什么不按{| h |-h[:fr]}@engineerinersmnky对u进行排序呢?相反,它更简单,而且通常更快。我的无知。你是对的,它确实提供了可读性,而且看起来性能稍微好一些。@engineersmnky,当然,还有arr.sort{g,h{h[:fr]g[:fr]}和arr.max_byarr.size{h}h[:fr]}虽然后者需要点击。@CarySwoveland是的,在ruby中有无数种方法可以做大多数事情,我通常会把重点放在两件事情上:性能,因为ruby从静态类型的语言和可读性开始,ruby真正的亮点。也就是说,我运行了sawa的代码,我的代码,你使用排序的变异和你通过fruity得到的答案,它报告说:排序比否定快10%+/-1%;否定和否定是相似的;反向排序比每个对象快30%+/-1%,因此,在我看来,您的评论实际上比提供的答案快,并且同样可读。与其按{h |-h[:fr]}@enginersmnky反向排序,不如直接排序,一般来说,速度更快。我的无知。你是对的,它确实提供了可读性,而且看起来性能稍微好一些。@engineersmnky,当然,还有arr.sort{g,h{h[:fr]g[:fr]}和arr.max_byarr.size{h}h[:fr]}虽然后者需要点击。@CarySwoveland是的,在ruby中有无数种方法可以做大多数事情,我通常会把重点放在两件事情上:性能,因为ruby从静态类型的语言和可读性开始,ruby真正的亮点。也就是说,我运行了sawa的代码,我的代码,你使用排序的变异和你通过fruity得到的答案,它报告说:排序比否定快10%+/-1%;否定和否定是相似的;reverse比每个_对象快30%+/-1%,因此您的评论实际上比提供的答案快,在我看来同样可读。如果哈希值很大,这将更节省内存,可能也更快。hash.new0非常有用,它们几乎应该使用hash.zero作为它的缩写。我想我错了。使用问题中的数组,示例中的组_大约快1.5-2倍。有了250万个条目的数组,示例组的速度提高了2倍以上。它的顶部有sort+reverse。神秘的是ruby的内部结构。我的测试数组是问题中的数组重复了很多次,所以它可能会有一些效果。如果散列基本上是唯一的,则可能会有所不同。对于100k个基本上是唯一的项,它们几乎一样快。如果散列很大,则内存效率会更高,也可能更快。hash.new0非常有用,它们几乎应该使用hash.zero作为它的简写。我想我错了。使用问题中的数组,示例中的组_大约快1.5-2倍。有了250万个条目的数组,示例组的速度提高了2倍以上。它的顶部有sort+reverse。神秘的是ruby的内部结构。我的测试数组是问题中的数组重复了很多次,所以它可能会有一些效果。如果散列大部分都是唯一的,那么可能会有所不同。对于100k大部分都是唯一的项目,它们的速度几乎一样快