evfwcqcg
evfwcqcg

Reputation: 16355

Immutable method to change attribute in an array of objects

I have a following array

Bot = Struct.new(:name, :age)

bots = %w(foo bar baz).map do |name|
  Bot.new(name, rand(10))
end

p bots
[ #<struct Bot name="foo", age=3>, 
  #<struct Bot name="bar", age=8>, 
  #<struct Bot name="baz", age=0> ]

I want to get a new array from bots, where age attribute converted to_s, but I don't want to change the real objects in the array bots. How can I do this?

Upvotes: 0

Views: 250

Answers (2)

SporkInventor
SporkInventor

Reputation: 3120

This will preserve bots:

new_bots = bots.map {|bot| Bot.new(bot.name, bot.age.to_s) }

This will not preserve bots:

new_bots = bots.map! {|bot| Bot.new(bot.name, bot.age.to_s) }

map! modifies the object it is called on, as do most methods that end in !. It is the mutable version of map.

map does not modify the contents of the object it is called on. Most array methods are immutable, except those that end in ! (but is only a convention, so be careful).

Upvotes: 1

Beno&#238;t
Beno&#238;t

Reputation: 15010

Bot = Struct.new(:name, :age)

bots = %w(foo bar baz).map do |name|
  Bot.new(name, rand(10))
end
#=> [#<struct Bot name="foo", age=4>,
#    #<struct Bot name="bar", age=5>,
#    #<struct Bot name="baz", age=8>]

bots.map { |bot| Bot.new(bot.name, bot.age.to_s)}
#=> [#<struct Bot name="foo", age="4">,
#    #<struct Bot name="bar", age="5">,
#    #<struct Bot name="baz", age="8">]

Upvotes: 1

Related Questions