array = ["Spam is bad", "Ham is good"]
I would like select the element(s) from the array which include(s) the word 'good' and set the string to a new variable. How could I do this?
Since neither answer so far instructs you on how to update the string in the array to the new value, here are some options:
# Find every string matching a criteria and change them
array.select{ |s| s.include? "good" }.each{ |s| s.replace( "bad" ) }
# Find every string matching a pattern and change them
array.grep.replace( "bad" ).each{ |s| s.replace( "bad" ) }
# Find the first string matching a criteria and change it
array.find{ |s| s =~ /good/ }.replace( "bad" )
However, all of the above will change every instance of a string. For example:
jon = Person.new "Johnny B. Goode"
array = [ jon.name, "cat" ]
array.find{ |s| s =~ /good/i }.replace( "bad" )
p array #=> "bad"
p jon #=> #<Person name="bad"> Uh oh...
If you don't want this side effect—if you want to replace the string in the array with a different string, but not change the string itself–then you need to find the index of the item and update that:
# Find the _first_ index matching some criteria and change it
array[ array.index{ |s| s =~ /good/ } ] = "bad"
# Update _every_ item in the array matching some criteria
array[i] = "bad" while i = array.index{ |s| s =~ /good/i }
# Another way to do the above
# Possibly more efficient for very large arrays any many items
indices = array.map.with_index{ |s,i| s =~ /good/ ? i : nil }.compact
indices.each{ |i| array[i] = "bad" }
Finally, the simplest and mostly fastest, without mucking about with indices:
# Create a new array with the new values
new_array = array.map do |s|
if s =~ /good/i # matches "Good" or "good" in the string
"bad"
else
s
end
end
# Same thing, but shorter syntax
new_array = array.map{ |s| s =~ /good/i ? "bad" : s }
# Or, change the array in place to the new values
new_array = array.map!{ |s| s =~ /good/i ? "bad" : s }
map! sounds like a good choice.
x = ['i', 'am', 'good']
def change_string_to_your_liking s
# or whatever it is you plan to do with s
s.gsub('good', 'excellente!')
end
x.map! {|i| i =~ /good/ ? change_string_to_your_liking(i) : i}
puts x.inspect
gsub), but replacing it wholesale.set the string to a new variable. For all we know that could mean create an integer value from the string. It could indeed require replacement, but this is not explicitly stated. Due to the ambiguity, I made no assumption on the exact intentions of variable modification and provided a method whose contents could easily be modified to his liking. Note the name of the method change_string_to_your_liking and the comment # or whatever it is you plan to do with s.There's also a special method for this:
array.grep(/good/) # => ["Ham is good"]
With #grep you can do a lot because it takes a regular expression...
grep is convenient, nothing prevents you from using a regex with select or find (as in my answer). Indeed, you can do much more with the block methods, e.g. select{ |s| s=~/good/i && s.length > 3 }.It's almost as you typed your title:
array.select {|s| s.include? "good"}
Here's the doc: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-select