从Ruby on Rails中的collection.map中排除选项?

我有这样的一行:

 {:value => (policy_address.state.name rescue nil)}, :required => true, :collection => states.map {|s| [ s.name, s.id] }, :include_blank => 'Please select'%> 

我想从states.map集合中排除一个值。 我认为这会起作用,但它没有:

  {:value => (policy_address.state.name rescue nil)}, :required => true, :collection => states.map {|s| [ s.name, s.id] unless s.name == "excluded_state" }, :include_blank => 'Please select'%> 

我输入unless s.name == "excluded_state ,但是,它再次,它不起作用:

我究竟做错了什么?

map不允许跳过值。 你必须先拒绝不需要的元素。

 states.reject { |s| s.name == "excluded_state" }.map { |s| [s.name, s.id] } 

另一个(更脏的)解决方案是为排除的元素返回nil ,并在结果数组上使用Array#compact来删除那些nil元素:

 states.map { |s| s.name == "excluded_state" ? nil : [s.name, s.id] }.compact 

尤里卡的答案很好,但这只是一个简短的解释,以澄清正在发生的事情。

map返回一个新数组,其中包含对数组中每个元素运行一次块的结果。 当你写[s.name, s.id] unless s.name == "excluded_state"这导致块在s.name == "excluded_state"时返回nil ,即结果会像

 [["NY", 1], nil, ["CA", 2]] 

所以你可以先使用reject来删除不需要的状态,或者你可以使用compact 1来删除你最初编写map结果时的nil条目。


  1. Array#compact返回删除了所有nil元素的数组副本。