通过另一个哈希表过滤Ruby哈希数组

3
也许我错过了一些显而易见的东西。似乎很难通过另一个哈希表或多个键/值对来过滤哈希表。
fruit = [
  { name: "apple",   color: "red",    pieable: true  },
  { name: "orange",  color: "orange", pieable: false },
  { name: "grape",   color: "purple", pieable: false },
  { name: "cherry",  color: "red",    pieable: true  },
  { name: "banana",  color: "yellow", pieable: true  },
  { name: "tomato",  color: "red",    pieable: false }
]
filter = { color: "red", pieable: true }

# some awesome one-liner? would return
[
  { name: "apple",   color: "red",    pieable: true  },
  { name: "cherry",  color: "red",    pieable: true  }
]      

我不认为散列数组是问题所在。我甚至不知道如何通过另一个任意散列来测试散列。我使用Rails,因此可以使用active_support等库之外的任何东西。

6个回答

2

可以把它变成单行代码,但是多行代码更加清晰。

fruit.select do |hash| # or use select!
  filter.all? do |key, value|
    value == hash[key]
  end
end

多行完全没问题。我至少尝试了五次才成功。这正是我想做的事情。太棒了 --> .all? 从未使用过。3 测试,4 断言,0 失败,0 错误,0 跳过 :) - squarism

1
如果您允许两行,它也可以被制作成一个高效的“一行代码”,如下所示:
keys, values = filter.to_a.transpose 
fruit.select { |f| f.values_at(*keys) == values }

1

虽然不是最高效的方法(你可以使用数组形式的filter来避免重复转换),但是:

fruit.select {|f| (filter.to_a - f.to_a).empty? }

1

我倾向于使用 Enumerable#group_by 来实现这个功能:

fruit.group_by { |g| { color: g[:color], pieable: g[:pieable] } }[filter]
  #=> [{:name=>"apple",  :color=>"red", :pieable=>true},
  #    {:name=>"cherry", :color=>"red", :pieable=>true}]

1

Tony Arcieri (@bascule)在Twitter上提供了这个非常好的解决方案。

require 'active_support/core_ext'  # unneeded if you are in a rails app
fruit.select { |hash| hash.slice(*filter.keys) == filter }

而且它有效。

# [{:name=>"apple", :color=>"red", :pieable=>true},
# {:name=>"cherry", :color=>"red", :pieable=>true}]

0

试试这个

fruit.select{ |hash| (filter.to_a & hash.to_a) == filter.to_a }

=> [{:name=>"apple", :color=>"red", :pieable=>true}, 
    {:name=>"cherry", :color=>"red", :pieable=>true}] 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接