基于过滤器从数组返回数据

时间:2018-01-20 23:03:55

标签: ruby ruby-on-rails-4

我有以下数组

person = [ {name: 'bob', weight: '160 lbs', hair: 'brown'},
            {name: 'bob', weight: '160 lbs', hair: 'brown'},
            {name: 'bob1', weight: '160 lbs', hair: 'brown'}, 
            {name: 'bob1',  weight: '160 lbs', hair: 'brown'}, 
            {name: 'bob1',  weight: '160 lbs', hair: 'brown'} 
]

我正在尝试根据输入参数名称和头发从数组中获取数据,以便它们可以作为单个或组合传递。

我尝试了以下代码,当名称和头发通过时它会起作用,但如果我只是传递头发,则会返回错误undefined local variable or method name

以下是我想要实现的案例: 如果name = bob和hair = brown通过,它应该返回前两个具有名称的哈希:' bob'并且对于bob1最后三个哈希名称:' bob1'如果只传递了重量或头发,它应该返回整个数组。

我相信我可以根据参数来编写条件,例如if name && hairif hair但是我必须重复我从数组中选择的代码。所以试着弄清楚是否可以用更清洁的方式来完成。

我如何更新它,以便我可以传递名字,头发和重量,一个或组合?

person.select { |hash| hash[:name] == name && hash[:hair] == hair  }

我正在执行的代码是:

person = [ {name: 'bob', weight: '160 lbs', hair: 'brown'},
            {name: 'bob', weight: '160 lbs', hair: 'brown'},
            {name: 'bob1', weight: '160 lbs', hair: 'brown'}, 
            {name: 'bob1',  weight: '160 lbs', hair: 'brown'}, 
            {name: 'bob1',  weight: '160 lbs', hair: 'brown'} 
]

# hair = 'brown'
# name = 'bob'
# person.select { |hash| hash[:name] == name &&
#                         hash[:hair] == hair  }
#   -->[{:name=>"bob", :weight=>"160 lbs", :hair=>"brown"}, {:name=>"bob", :weight=>"160 lbs", :hair=>"brown"}]                      

# hair = 'brown'
# name = 'bob1'
# person.select { |hash| hash[:name] == name &&
#                         hash[:hair] == hair  }
  # -->[{:name=>"bob1", :weight=>"160 lbs", :hair=>"brown"}, {:name=>"bob1", :weight=>"160 lbs", :hair=>"brown"}, {:name=>"bob1", :weight=>"160 lbs", :hair=>"brown"}]

hair = 'brown'
person.select { |hash| hash[:name] == name &&
                        hash[:hair] == hair  }
# --> return entire person array                

1 个答案:

答案 0 :(得分:3)

person = [
  { name: 'Bob',      weight: '160 lbs', hair: 'brown' },
  { name: 'Bub',      weight: '170 lbs', hair: 'none'  },
  { name: 'Wilma',    weight: '160 lbs', hair: 'brown' }, 
  { name: 'Gertrude', weight: '120 lbs', hair: 'blue'  }, 
  { name: 'Bob',      weight: '160 lbs', hair: 'brown' } 
]

def select_matches(person, target)
  keys = target.keys
  person.select { |h| h.select { |k| keys.include?(k) } == target }
end 

select_matches(person, name: 'Bob', weight: '160 lbs', hair: 'brown')
  #=> [{:name=>"Bob", :weight=>"160 lbs", :hair=>"brown"},
  #    {:name=>"Bob", :weight=>"160 lbs", :hair=>"brown"}]
select_matches(person, weight: '160 lbs', hair: 'brown')
  #=> [{:name=>"Bob", :weight=>"160 lbs", :hair=>"brown"},
  #    {:name=>"Wilma", :weight=>"160 lbs", :hair=>"brown"},
  #    {:name=>"Bob", :weight=>"160 lbs", :hair=>"brown"}] 
select_matches(person, name: 'Gertrude')
  #=> [{:name=>"Gertrude", :weight=>"120", :hair=>"blue"}]

请注意

select_matches(person, weight: '160 lbs', hair: 'brown')

的简写
select_matches(person, { weight: '160 lbs', hair: 'brown' })

在Ruby 2.5中,倒数第二行可以写成

person.select { |h| h.slice(*keys) == target }

Hash#slice。切片很好,嗯?