Turbo
Turbo

Reputation: 29

Interacting with array elements in Ruby

I'm trying to do a couple things with my code and I am confused as to how to interact with the elements of an array. The point of this code is to take a string as an input and redact certain words.

My goals are:

  1. Have my program redact multiple words.

  2. Make a new redacted string and save it as a variable, rather than just printing it to the console

I've outlined my logic using comments (couple of questions in the comments too).

puts "Write something: "

text = gets.chomp

puts "Redact some words: "

redact = gets.chomp

words = text.split(" ")  #Turns string into array of words

redact_words = text.split(" ")

words.each do |word|        #Iterates through each component of array [words] and permanently  
word.downcase!              #makes the placeholder (word) lower case.
 end                        #Apparently this works also: words.map!(&:downcase) to make it
                              #undercase but I'm not sure why? What is .map? What is &:?

words.each do |word|

if redact_words.include?(word)   #iterates through each component of array [redact_words] and 
                                 #checks if it includes the placeholder (word). If it does,
text.gsub!("#{word}","REDACTED") # it permanently globally substitutes the string of placeholder
                                 #(word) with the string "REDACTED".
else puts "No redactable word(s) found"
end
end
puts text

My code isn't working that well however because its not seeing capitalization.

If you put in "Hello hello Okay okay" as the first input. And "hello okay" as the second input. You get "Hello REDACTED Okay REDACTED as the output.

I think its because its printing the modified string text and NOT the array [words] (which is kind of what I want because I want the redacted string to be saved to a variable). Is there another way to do this?

Also, is there a way to do the substitution I did except use regexp (regular expressions)?

Upvotes: 1

Views: 415

Answers (2)

rdubya
rdubya

Reputation: 2916

To answer your question as to why words.map!(&:downcase) works:

  1. Like each, map loops over each item in an array passing that item to the given block. The difference is that it creates a new array with the returned items. map! replaces the items in the current array with the returned items instead of creating a new array. reference
  2. The &:downcase is a shortcut for {|x| x.downcase }. It essentially calls the specified method on each item in the array and uses the returned value as the new value.

Here is a version of your script for you using regular expressions:

puts "Write something: "

text = gets.chomp

puts "Redact some words: "

redact = gets.chomp

redact_words = redact.split(" ")

# The %r syntax creates a regular expression using interpolation, the /i means to ignore case
new_text = text.gsub(%r/\b(#{redact_words.join('|')})\b/i, 'REDACTED')

puts "No redactable word(s) found" if new_text == text

puts new_text

Upvotes: 1

Uri Agassi
Uri Agassi

Reputation: 37419

You should make your search case-insensitive.

The simplest way is to build a regular expression (using Regexp.union), and then matching it to the whole string:

def redact(text, redact)
  redact_words = redact.split(" ")  
  redact_patterns = redact_words.map { |word| /\b#{word}\b/i } # /i makes it case insensitive, 
                                                               # \b makes it whole word only
  text.gsub(Regexp.union(redact_patterns), 'REDACTED')
end

redact('Hello hello Okay okay', "hello okay")
# => "REDACTED REDACTED REDACTED REDACTED"

Upvotes: 0

Related Questions