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

Rya*_*yan 11 ruby ruby-on-rails

我有这样一条线:

<%= f.input :state_id, :input_html => {:value => (policy_address.state.name rescue nil)}, :required => true, :collection => states.map {|s| [ s.name, s.id] }, :include_blank => 'Please select'%>
Run Code Online (Sandbox Code Playgroud)

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

<%= f.input :state_id, :input_html => {: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'%>
Run Code Online (Sandbox Code Playgroud)

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

我究竟做错了什么?

Eur*_*eka 23

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

states.reject { |s| s.name == "excluded_state" }.map { |s| [s.name, s.id] }
Run Code Online (Sandbox Code Playgroud)

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

states.map { |s| s.name == "excluded_state" ? nil : [s.name, s.id] }.compact
Run Code Online (Sandbox Code Playgroud)

  • `states.map {| s | [s.name,s.id] if s.name =="excluded_state"} .compact` (4认同)

mik*_*kej 6

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

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

[["NY", 1], nil, ["CA", 2]]
Run Code Online (Sandbox Code Playgroud)

因此,您可以先使用reject删除不需要的状态,或者只使用compact1删除最初编写它nil的结果条目map.


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