我有一个数组和一个哈希:
a = [
{ :color => "blue", :name => "wind" },
{ :color => "red", :name => "fire" },
{ :color => "white", :name => "wind" },
{ :color => "yellow", :name => "wind" },
{ :color => "green", :name => nil },
{ :color => "black", :name => "snow" }
]
b = { blue: 'blue', white: 'white', red: 'red', green: 'green', black: 'black' }
我需要找到基于输入哈希的唯一名称来获得这个:
['wind', 'fire', 'snow']
我试过了:
names = a.map { |i| [i[:color], i[:name]] }
.delete_if { |key, value| value.nil? }
resultant_names = []
b.values.each do |c|
if names[c]
resultant_names << names[c]
end
end
resultant_names.uniq
我需要一个更好的方法。这个有太多的循环。
答案 0 :(得分:2)
虽然你的结果对我来说没有意义(例如它缺少雪)但这将起作用
a.map(&:values).reverse.to_h.values_at(*b.values).compact.uniq
#=> ["wind","fire"]
要打破它:
a.map(&:values).reverse.to_h
#=> {"white"=>"wind", "green"=>nil, "yellow"=>"wind", "red"=>"fire", "blue"=>"wind"}
您注意到雪已经丢失,因为当我们撤消列表时,["white","wind"]
会在转换为["white","snow"]
时覆盖Hash
然后我们只从
收集给定颜色的值b.values
#=> ["blue", "white", "red", "green"]
a.map(&:values).reverse.to_h.values_at(*b.values)
#=> ["wind", "wind", "fire", nil]
然后Array#compact
将删除nil
元素,Array#uniq
将使列表唯一。
如果打算下雪,你可以跳过逆转
a.map(&:values).to_h.values_at(*b.values).compact.uniq
#=> ["wind", "snow", "fire"]
无论哪种方式,这都是一个奇怪的数据结构,这些答案只是为了帮助解决所提供的问题,因为重复的颜色可能导致基于a
中的顺序的不同结果。
答案 1 :(得分:1)
我相信你想要&#39; snow&#39;在你的输出数组中,因为没有其他逻辑解释。如果您要在第2行的末尾添加.to_h
,您的代码将会起作用,但正如您所说,它不是非常干净或高效。此外,通过转换为哈希,由于重复键,您可能会丢失数据。
这是一个更严格的构造,可以避免数据丢失问题:
def unique_elements(a, b)
color_set = b.values.to_set
a.map { |pair| pair[:name] if color_set.include?(pair[:color]) }.compact.uniq
end
首先,我们取b
的值并将它们转换为集合,以便我们可以有效地确定给定元素是否是集合的成员。
接下来,我们会在a
上映射,选择a
成员的名称,[:color]
包含在我们的颜色集中。
最后,我们删除nils
(使用compact
)并选择唯一值。
>> unique_elements(a, b)
#> ["wind", "fire", "snow"]
答案 2 :(得分:1)
我首先将a
转换为更有用的数据结构。
h = a.each_with_object({}) { |g,h| h[g[:color]] = g[:name] }
#=> {"blue"=>"wind", "red"=>"fire", "white"=>"wind", "yellow"=>"wind",
# "green"=>nil, "black"=>"snow"}
我们可以简单地写一下
h.values_at(*b.values).compact.uniq
# => ["wind", "fire", "snow"]
这种方法有几个可取的特征:
h
的创建使该方法更易于阅读h
作为单独的步骤h
只需要创建一次即使要评估多个b
值(在这种情况下我们可能希望h
为实例变量)。 h
可以链接到第二个声明,但由于上面给出的原因(特别是最后一个),我选择不这样做。