Map an array modifying only elements matching a certain condition
Because arrays are pointers, this also works:
a = ["hello", "to", "you", "dude"]a.select {|i| i.length <= 3 }.each {|i| i << "!" }puts a.inspect# => ["hello", "to!", "you!", "dude"]
In the loop, make sure you use a method that alters the object rather than creating a new object. E.g. upcase!
compared to upcase
.
The exact procedure depends on what exactly you are trying to achieve. It's hard to nail a definite answer with foo-bar examples.
I agree that the map statement is good as it is. It's clear and simple,, and would easyfor anyone to maintain.
If you want something more complex, how about this?
module Enumerable def enum_filter(&filter) FilteredEnumerator.new(self, &filter) end alias :on :enum_filter class FilteredEnumerator include Enumerable def initialize(enum, &filter) @enum, @filter = enum, filter if enum.respond_to?(:map!) def self.map! @enum.map! { |elt| @filter[elt] ? yield(elt) : elt } end end end def each @enum.each { |elt| yield(elt) if @filter[elt] } end def each_with_index @enum.each_with_index { |elt,index| yield(elt, index) if @filter[elt] } end def map @enum.map { |elt| @filter[elt] ? yield(elt) : elt } end alias :and :enum_filter def or FilteredEnumerator.new(@enum) { |elt| @filter[elt] || yield(elt) } end endend%w{ a b c }.on { |x| x == 'b' }.map { |x| x + "!" } #=> [ 'a', 'b!', 'c' ]require 'set'Set.new(%w{ He likes dogs}).on { |x| x.length % 2 == 0 }.map! { |x| x.reverse } #=> #<Set: {"likes", "eH", "sgod"}>('a'..'z').on { |x| x[0] % 6 == 0 }.or { |x| 'aeiouy'[x] }.to_a.join #=> "aefiloruxy"