Map an array modifying only elements matching a certain condition Map an array modifying only elements matching a certain condition ruby ruby

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.


old_a.map! { |a| a == "b" ? a + "!" : a }

gives

=> ["a", "b!", "c"]

map! modifies the receiver in place, so old_a is now that returned array.


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"