如何从Ruby中的哈希数组中获取唯一元素?

我有一个哈希数组,我想要它的唯一值。 调用Array.uniq并不能满足我的期望。

 a = [{:a => 1},{:a => 2}, {:a => 1}] a.uniq # => [{:a => 1}, {:a => 2}, {:a => 1}] 

我期望的地方:

 [{:a => 1}, {:a => 2}] 

在网上搜索时,我没有想出一个我满意的解决方案。 人们建议重新定义Hash.eql?Hash.hash ,因为这是Array.uniq查询的内容。

编辑:在现实世界中遇到这个问题时,哈希值稍微复杂一些。 它们是解析的JSON的结果,它具有多个字段,其中一些值也是哈希值。 我有一系列的结果,我想过滤掉唯一的值。

我不喜欢重新定义Hash.eql?Hash.hash解决方案,因为我要么必须全局重新定义Hash ,要么为我的数组中的每个条目重新定义它。 为每个条目更改Hash的定义会很麻烦,尤其是因为每个条目中可能存在嵌套的哈希值。

在全球范围内改变Hash有一些潜力,特别是如果它是暂时完成的话。 我想构建另一个类或辅助函数来包装保存旧的定义并恢复它们,但我认为这会增加实际需要的复杂性。

使用inject似乎是重新定义Hash一个很好的选择。

我可以通过调用inject获得我想要的东西

 a = [{:a => 1},{:a => 2}, {:a => 1}] a.inject([]) { |result,h| result << h unless result.include?(h); result } 

这将返回:

 [{:a=>1}, {:a=>2}] 

Ruby 1.8.7+将返回您所期望的内容:

 [{:a=>1}, {:a=>2}, {:a=>1}].uniq #=> [{:a=>1}, {:a=>2}] 

我有类似的情况,但哈希有钥匙。 我用的是排序方法。

我的意思是说:

你有一个数组:

 [{:x=>1},{:x=>2},{:x=>3},{:x=>2},{:x=>1}] 

你排序它( #sort_by {|t| t[:x]} )并得到这个:

 [{:x=>1}, {:x=>1}, {:x=>2}, {:x=>2}, {:x=>3}] 

现在Aaaron Hinni的答案有点修改过:

 your_array.inject([]) do |result,item| result << item if !result.last||result.last[:x]!=item[:x] result end 

我也尝试过:

 test.inject([]) {|r,h| r< 

但它很慢。 这是我的基准:

 test=[] 1000.times {test<<{:x=>rand}} Benchmark.bmbm do |bm| bm.report("sorting: ") do test.sort_by {|t| t[:x]}.inject([]) {|r,h| r< 

结果:

 Rehearsal --------------------------------------------- sorting: 0.010000 0.000000 0.010000 ( 0.005633) inject: 0.470000 0.140000 0.610000 ( 0.621973) ------------------------------------ total: 0.620000sec user system total real sorting: 0.010000 0.000000 0.010000 ( 0.003839) inject: 0.480000 0.130000 0.610000 ( 0.612438) 

假设您的哈希值始终是单键值对,这将起作用:

 a.map {|h| h.to_a[0]}.uniq.map {|k,v| {k => v}} 

Hash.to_a创建一个键值数组数组,因此第一个映射可以实现:

 [[:a, 1], [:a, 2], [:a, 1]] 

uniq on Arrays做你想要的,给你:

 [[:a, 1], [:a, 2]] 

然后第二张地图再次将它们重新组合成哈希值。

你可以使用(在ruby 1.9.3中测试过),

 [{a: 1},{a: 2},{a:1}].uniq => [{a:1},{a: 2}] [{a: 1,b: 2},{a: 2, b: 2},{a: 1, b: 3}].uniq_by {|v| v[:a]} => [{a: 1,b: 2},{a: 2, b: 2}] 

你给出的答案类似于这里讨论的答案。 它会覆盖hasheql? 哈希中出现在数组中的方法,然后使uniq正确运行。

发现于谷歌http://mikeburnscoder.wordpress.com/2008/01/18/uniquify-an-array-of-hashes-in-ruby/

数组上的管道方法(自1.8.6起可用)执行set union(返回数组),因此以下是获取任何数组a唯一元素的另一种可能方法:

[] | a