Help me get rid of the space " " - ruby

def name
#name || "#{self.first_name} #{self.last_name}"
end
If first name and last name are both empty name is a space " ". How do I rewrite the right-hand side so it's an empty string "" instead of a space " "?

You can just add .strip at the end:
>> ln = 'last' #=> "last"
>> fn = 'first' #=> "first"
>> "#{fn} #{ln}".strip #=> "first last"
>> fn = nil #=> nil
>> ln = nil #=> nil
>> "#{fn} #{ln}".strip #=> ""

def name
#name ||= [first_name, last_name].compact * " "
end
This solution has the advantage of not including a trailing or leading space when either name is nil, and it works in the general case (i.e. for any number of strings).

Related

Replace matched lines in a file but ignore commented-out lines using Ruby

How to replace a file in Ruby, but do not touch commented-out lines? To be more specific I want to change variable in configuration file. An example would be:
irb(main):014:0> string = "#replaceme\n\t\s\t\s# replaceme\nreplaceme\n"
=> "#replaceme\n\t \t # replaceme\nreplaceme\n"
irb(main):015:0> puts string.gsub(%r{replaceme}, 'replaced')
#replaced
# replaced
replaced
=> nil
irb(main):016:0>
Desired output:
#replaceme
# replaceme
replaced
I don't fully understand the question. To do a find and replace in each line, disregarding text following a pound sign, one could do the following.
def replace_em(str, source, replacement)
str.split(/(\#.*?$)/).
map { |s| s[0] == '#' ? s : s.gsub(source, replacement) }.
join
end
str = "It was known that # that dog has fleas, \nbut who'd know that that dog # wouldn't?"
replace_em(str, "that", "the")
#=> "It was known the # that dog has fleas, \nbut who'd know the the dog # wouldn't?"
str = "#replaceme\n\t\s\t\s# replaceme\nreplaceme\n"
replace_em(str, "replaceme", "replaced")
#=> "#replaceme\n\t \t # replaceme\nreplaced\n"
For the string
str = "It was known that # that dog has fleas, \nbut who'd know that that dog # wouldn't?"
source = "that"
replacement = "the"
the steps are as follows.
a = str.split(/(\#.*?$)/)
#=> ["It was known that ", "# that dog has fleas, ",
# "\nbut who'd know that that dog ", "# wouldn't?"]
Note that the body of the regular expression must be put in a capture group in order that the text used to split the string be included as elements in the resulting array. See String#split.
b = a.map { |s| s[0] == '#' ? s : s.gsub(source, replacement) }
#=> ["It was known the ", "# that dog has fleas, ",
# "\nbut who'd know the the dog ", "# wouldn't?"]
b.join
#=> "It was known the # that dog has fleas, \nbut who'd know the the dog # wouldn't?"
How about this?
puts string.gsub(%r{^replaceme}, 'replaced')

How do I apply removing of characters to the string itself?

Using Ruby 2.4. How do I apply an editing of a stirng to the string itself? I have this method
# Removes the word from teh end of the string
def remove_word_from_end_of_str(str, word)
str[0...(-1 * word.length)]
end
I want the parameter to be operated upon, but it isn't working ...
2.4.0 :001 > str = "abc def"
=> "abc def"
2.4.0 :002 > StringHelper.remove_word_from_end_of_str(str, "def")
=> "abc "
2.4.0 :003 > str
=> "abc def"
I want the string that was passed in to be equal to "abc " but that isn't happening. I don't want to set the variable to the result of the function (e.g. "str = StringHelper.remove(...)"
Ruby already has the String#delete! method that does exactly this:
>> str = 'abc def'
=> "abc def"
>> word = 'def'
=> "def"
>> str.delete!(word)
=> "abc "
>> str
=> "abc "
Note that this will remove all instances of word:
>> str = 'def abc def'
=> "def abc def"
>> str.delete!(word)
=> " abc "
To limit the effect to only the last word, you can do:
>> str = 'def abc def'
=> "def abc def"
>> str.slice!(-word.length..-1)
=> "def"
>> str
=> "def abc "
str[range] is just a shorthand for str.slice(range). You just have to use the destructive method, like that :
# Removes the word from the end of the string
def remove_word_from_end_of_str(str, word)
str.slice!((str.length - word.length)...(str.length))
end
For more information, see the documentation.
If you want your function to return the new string as well, you should use :
# Removes the word from the end of the string
def remove_word_from_end_of_str(str, word)
str.slice!((str.length - word.length)...(str.length))
str
end
Try:
def remove_word_from_end_of_str(str, word)
str.slice!((str.length - word.length)..str.length)
end
Also, your explanation is a little confusing. You are calling the remove_word method as a class method but it is an instance method.
chomp! returns a the String with the given record separator removed from the end of string (if present), and nil if nothing was removed.
def remove_word_from_end_of_str(str, word)
str.chomp!( "CO")
end
str = "Aurora CO"
remove_word_from_end_of_str(str, "CO")
p str #=> "Aurora "

Replacing "\n" but not "\n\n"

How to replace "\n" but not "\n\n" etc. with " \n"?
text1 = "Hello\nWorld"
text1.sub! "\n", " \n"
=> "Hello \nWorld"
text2 = "Hello\n\nWorld"
text2.sub! "\n\n", " \n"
=> "Hello \n\nWorld"
SHOULD BE: => "Hello\n\nWorld"
You can use the regular expression /(?<!\n)\n(?!\n)/, which matches a \n only when it's not prefixed with another \n and not followed by a \n.
text1 = "Hello\nWorld"
# => "Hello\nWorld"
text1.sub /(?<!\n)\n(?!\n)/, " \n"
# => "Hello \nWorld"
text2 = "Hello\n\nWorld"
# => "Hello\n\nWorld"
text2.sub /(?<!\n)\n(?!\n)/, " \n"
# => "Hello\n\nWorld"
Here's another way:
r = /\n+/
"Hello\nWorld".sub(r) { |s| (s.size==1) ? " \n" : s }
#=> "Hello \nWorld"
"Hello\n\nWorld".sub(r) { |s| (s.size==1) ? " \n" : s }
#=> "Hello\n\nWorld"
and one more:
h = Hash.new { |h,k| h[k] = k }.update("\n"=>" \n")
#=> {"\n"=>" \n"}
"Hello\nWorld".sub(r,h)
#=> "Hello \nWorld"
"Hello\n\nWorld".sub(r,h)
#=> "Hello\n\nWorld"
In the latter method, each string of one or more consecutive newline characters is passed to the hash. If it's a single newline, "\n" is replaced with h["\n"] #=> " \n". If it's two or more newlines, say s = "\n\n", and h does not have a key equal to s (initally it won't), the key-value pair s=>s will be added to h (because of the default value defined for the hash) and s will be replaced by itself.
Another solution you could use:
string = "Hello\nWorld"
string.split("\n") == string.split("\n").reject(&:empty?) ? string.sub!("\n", " \n") : string
#=> "Hello \nWorld"
string = "Hello\n\nWorld"
string.split("\n") == string.split("\n").reject(&:empty?) ? string.sub!("\n", " \n") : string
#=> "Hello\n\nWorld"

Function to strip!, then convert zero-length string to nil

What's the most-efficient manner to remove beginning and ending spaces around a string, then convert the string to nil if the resulting value is zero-length?
For example:
> a=''
> squash(a)
=> nil
> a=' '
> squash(a)
=> nil
> a=' xyz '
> squash(a)
=> 'xyz'
> a=nil
> squash(a)
=> nil
Thus far:
def squash(value)
return nil if value.nil?
value.strip!
(value.blank? ? nil : value)
end
Seems like there could be a more-terse way of implementing this.
** edit **
While I am working in Rails, it would be nice if the answer would contain a Ruby-only implementation, too.
I should emphasize that the implementation needs to be able to handle a string with a nil value.
Assuming you want this for rails (otherwise blank? is undefined) you can use presence method:
def squash(value)
value && value.strip.presence
end
In pure ruby, I would do:
def squash(value)
return unless value
value = value.strip
value unless value.empty?
end
This will work with plain Ruby:
def squash(str)
str = str.to_s.strip
str unless str.empty?
end
Here's one way:
def squash(str)
(str && str[/\S/]) ? str.strip : nil
end
/\S/ looks for a character that is not whitespace.
squash " My dog has fleas. " #=> "My dog has fleas."
squash " " #=> nil
squash nil #=> nil
Reader challenge
I tried to also implement squash!, that would convert the argument str in place. If str is nil, just leave it alone. If str contains a least one non-whitespace character, then str.strip!. However, I could not figure out a way to convert a string to nil. I wanted to do this when the string is empty or contains only whitespace, but the problem is to convert any string, or more generally, any non-nil object, to nil, when the object is received as a method argument. Can it be done? [Edit: #Stefan says the type cannot be changed. I'm sure he's right, but I would like to see where that is written and understand why it is not permitted. Anyone? tidE].
This handles all your examples.
def squash(value)
value.to_s.strip.empty? ? nil : value.strip
end
Just adding this because it's short:
def squash(str)
str.to_s[/\S(.*\S)?/]
end
squash(nil) #=> nil
squash("") #=> nil
squash(" ") #=> nil
squash("a") #=> "a"
squash(" a") #=> "a"
squash("a ") #=> "a"
squash(" a ") #=> "a"
squash(" foo ") #=> "foo"
squash(" foo bar ") #=> "foo bar"
Here's a plain ruby version:
def squash(str)
str && str.strip! && (str unless str.empty?)
end
Update - If you want a version without side effects:
def squash(str)
str && (x = str.strip) && (x unless x.empty?)
end
If you want the method name squash with argument value.
def squash(value)
return value unless value.instance_of?(String)
return if value.strip!&.empty?
value
end
Features:
Works either on pure Ruby or Ruby on Rails
Works with other data types than string as well, for example, you can pass a number if you want
Testing:
squash('ok')
#=> ok
squash('')
#=> nil
squash(' ')
#=> nil
squash(' xyz ')
#=> 'xyz'
squash('xyz ')
#=> 'xyz'
squash(' xyz')
#=> 'xyz'
squash(123)
#=> 123
squash(nil)
#=> nil
Note:
I use safe navigation operator, which was released in Ruby 2.3.0. So make sure before using it.
irb(main):001:0> s = " string "
=> " string "
irb(main):002:0> s.strip!
=> "string"
irb(main):003:0> s.blank?
NoMethodError: undefined method `blank?' for "string":String
from (irb):3
from C:/RUBY/BIN/irb:12:in `'
irb(main):004:0>
I think blank is not Ruby but Rails? Anyway, what's wrong with
(value.length == 0 ? nil : value)
or even better
value.empty? ? nil : value
At least everybody would understand what the intention is here.

Check if array contains string, case insensitive

I'm trying to write an application that removes words from a list of words:
puts "Words:"
text = gets.chomp
puts "Words to remove:"
remove = gets.chomp
words = text.split(" ")
removes = remove.split(" ")
words.each do |x|
if removes.include.upcase? x.upcase
print "REMOVED "
else
print x, " "
end
end
How would I make this case insensitive?
I tried putting .upcase in there but no luck.
words.each do |x|
if removes.select{|i| i.downcase == x.downcase} != []
print "REMOVED "
else
print x, " "
end
end
array#select will select any element from the array if the block yields true. So if select do not select any element and return an empty array, it is not in the array.
Edit
You can also use if removes.index{|i| i.downcase==x.downcase}. It performs better than select since it does not create a temporary array and returns whenever it finds the first match.
puts "Words:"
text = gets.chomp
puts "Words to remove:"
remove = gets.chomp
words = text.split(" ")
removes = remove.upcase.split(" ")
words.each do |x|
if removes.include? x.upcase
print "REMOVED "
else
print x, " "
end
end

Resources