simplest way to check for just spaces in ruby - ruby

So I know in ruby that x.nil? will test if x is null.
What is the simplest way to test if x equals ' ', or ' '(two spaces), or ' '(three spaces), etc?
Basically, I'm wondering what the best way to test if a variable is all whitespace?

If you are using Rails, you can simply use:
x.blank?
This is safe to call when x is nil, and returns true if x is nil or all whitespace.
If you aren't using Rails you can get it from the activesupport gem. Install with gem install activesupport. In your file either require 'active_support/core_ext to get all active support extensions to the base classes, or require 'active_support/core_ext/string' to get just the extensions to the String class. Either way, the blank? method will be available after the require.

"best" depends on the context, but here is a simple way.
some_string.strip.empty?

s =~ /\A\s*\Z/
Regex solution. Here's a short ruby regex tutorial.

If x is all whitespace, then x.strip will be the empty string. So you can do:
if not x.nil? and x.strip.empty? then
puts "It's all whitespace!"
end
Alternatively, using a regular expression, x =~ /\S/ will return false if and only if x is all whitespace characters:
if not (x.nil? or x =~ /\S/) then
puts "It's all whitespace!"
end

a = " "
a.each_byte do |x|
if x == 32
puts "space"
end
end

Based on your comment I think you can extend the String class and define a spaces? method as follows:
$ irb
>> s = " "
=> " "
>> s.spaces?
NoMethodError: undefined method `spaces?' for " ":String
from (irb):2
>> class String
>> def spaces?
>> x = self =~ /^\s+$/
>> x == 0
>> end
>> end
=> nil
>> s.spaces?
=> true
>> s = ""
=> ""
>> s.spaces?
=> false
>>

s.include?(" ")
Examples:
s = "A B C D"
s.include?(" ") #=> true
s = "ABCD"
s.include?(" ") #=> false

Yet another :) string.all? { |c| c == ' ' }

Related

Not sure why this simple regex matching code won't work

# #!/usr/local/bin/ruby
puts "why doesn't this work??"
pi = ''
special = "[;\`'<>-]"
regex = /[#{special.gsub(/./){|char| "\\#{char}"}}]/
pi = ARGV[0].to_s #takes in console argument to test
if pi == '3.1415926535897932385'
puts "got it"
end
if pi =~ regex
puts "stop word"
else
puts "incorrect"
end
All I'm trying to do is test whether or not the pi variable contains any of the stop characters, if true, print "stop word" otherwise got it or incorrect respectively. I've tried doing this about ten ways. with scans, include? lines and I feel like this is the best route.
I think you may be over-thinking this. Here are a couple of ways (among many), where true means that the string contains at least one of the special characters):
#1
baddies = "[;`'<>-]"
pi = '3.14'
pi.delete(baddies).size < pi.size #=> false
pi = '3.1;4'
pi.delete(baddies).size < pi.size #=> true
#2
special = %w| [ ; ` ' < > - ] |
# => ["[", ";", "`", "'", "<", ">", "-", "]"]
pi = '3.14'
(pi.chars & special).any? #=> false
pi = '3.1cat4'
(pi.chars & special).any? #=> false
pi = '3.1;4'
(pi.chars & special).any? #=> true
You don't need to escape any of the characters in your character class:
special = "[;\`'<>-]"
regex = /#{special}/
p regex
#pi = ARGV[0] #takes in console argument to test
pi = 'hello;world'
if pi == '3.1415926535897932385'
puts "got it"
end
if pi =~ regex
puts "stop word"
else
puts "incorrect"
end
--output:--
/[;`'<>-]/
stop word
And ARGV[0] is a string already. But, a shell/console also recognizes special characters when you enter them on the command line:
special = "[;\`'<>-]"
#regex = /[#{special.gsub(/./){|char| "\\#{char}"}}]/
regex = /#{special}/
p regex
pi = ARGV[0] #takes in console argument to test
if pi == '3.1415926535897932385'
puts "got it"
end
if pi =~ regex
puts "stop word"
else
puts "incorrect"
end
--output:--
~/ruby_programs$ ruby 1.rb ;
/[;`'<>-]/
incorrect
~/ruby_programs$ ruby 1.rb <
-bash: syntax error near unexpected token `newline'
If you want the shell/console to treat the special characters that it recognizes--as literals, then you have to quote them. There are various ways to quote things in a shell/console:
~/ruby_programs$ ruby 1.rb \;
/[;`'<>-]/
stop word
~/ruby_programs$ ruby 1.rb \<
/[;`'<>-]/
stop word
Note you can use String#[] too:
special = "[;\`'<>-]"
regex = /#{special}/
...
...
if pi[regex]
puts "stop word"
else
puts "incorrect"
end

Why does Ruby not Symbol#=~ (regex match operator)?

Ruby doesn't automatically stringify symbols when performing a regex match on them, which is easy to do when you have variables containing symbols and you forget that you need to call #to_s on them before trying a regex match:
>> :this =~ /./
=> false
>> :this =~ :this
=> false
>> :this =~ /:this/
=> false
It turns out that :=~ is defined in Object, Ruby 1.8's primordial class:
http://rubybrain.com/api/ruby-1.8.7/doc/index.html?a=M000308&name==~
Of course, the implementation just returns false, leaving it up to subclasses like String and Regexp to provide meaningful implementations.
So why doesn't Symbol provide something like the following?
def =~(pattern)
self.to_s =~ pattern
end
Any Ruby linguists out there know?
I don't know the reason why it was decided that 1.8 should behave this way, but 1.9 changed in that regard:
>> RUBY_VERSION #=> "1.9.2"
>> :this =~ /./ #=> 0
>> :this =~ /is/ #=> 2

Ruby: How to get the first character of a string

How can I get the first character in a string using Ruby?
Ultimately what I'm doing is taking someone's last name and just creating an initial out of it.
So if the string was "Smith" I just want "S".
You can use Ruby's open classes to make your code much more readable. For instance, this:
class String
def initial
self[0,1]
end
end
will allow you to use the initial method on any string. So if you have the following variables:
last_name = "Smith"
first_name = "John"
Then you can get the initials very cleanly and readably:
puts first_name.initial # prints J
puts last_name.initial # prints S
The other method mentioned here doesn't work on Ruby 1.8 (not that you should be using 1.8 anymore anyway!--but when this answer was posted it was still quite common):
puts 'Smith'[0] # prints 83
Of course, if you're not doing it on a regular basis, then defining the method might be overkill, and you could just do it directly:
puts last_name[0,1]
If you use a recent version of Ruby (1.9.0 or later), the following should work:
'Smith'[0] # => 'S'
If you use either 1.9.0+ or 1.8.7, the following should work:
'Smith'.chars.first # => 'S'
If you use a version older than 1.8.7, this should work:
'Smith'.split(//).first # => 'S'
Note that 'Smith'[0,1] does not work on 1.8, it will not give you the first character, it will only give you the first byte.
"Smith"[0..0]
works in both ruby 1.8 and ruby 1.9.
For completeness sake, since Ruby 1.9 String#chr returns the first character of a string. Its still available in 2.0 and 2.1.
"Smith".chr #=> "S"
http://ruby-doc.org/core-1.9.3/String.html#method-i-chr
In MRI 1.8.7 or greater:
'foobarbaz'.each_char.first
Try this:
>> a = "Smith"
>> a[0]
=> "S"
OR
>> "Smith".chr
#=> "S"
In Rails
name = 'Smith'
name.first
>> s = 'Smith'
=> "Smith"
>> s[0]
=> "S"
Another option that hasn't been mentioned yet:
> "Smith".slice(0)
#=> "S"
Because of an annoying design choice in Ruby before 1.9 — some_string[0] returns the character code of the first character — the most portable way to write this is some_string[0,1], which tells it to get a substring at index 0 that's 1 character long.
Try this:
def word(string, num)
string = 'Smith'
string[0..(num-1)]
end
If you're using Rails You can also use truncate
> 'Smith'.truncate(1, omission: '')
#=> "S"
or for additional formatting:
> 'Smith'.truncate(4)
#=> "S..."
> 'Smith'.truncate(2, omission: '.')
#=> "S."
While this is definitely overkill for the original question, for a pure ruby solution, here is how truncate is implemented in rails
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 66
def truncate(truncate_at, options = {})
return dup unless length > truncate_at
omission = options[:omission] || "..."
length_with_room_for_omission = truncate_at - omission.length
stop = if options[:separator]
rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
else
length_with_room_for_omission
end
"#{self[0, stop]}#{omission}"
end
Other way around would be using the chars for a string:
def abbrev_name
first_name.chars.first.capitalize + '.' + ' ' + last_name
end
Any of these methods will work:
name = 'Smith'
puts name.[0..0] # => S
puts name.[0] # => S
puts name.[0,1] # => S
puts name.[0].chr # => S

What is the canonical way to trim a string in Ruby without creating a new string?

This is what I have now - which looks too verbose for the work it is doing.
#title = tokens[Title].strip! || tokens[Title] if !tokens[Title].nil?
Assume tokens is a array obtained by splitting a CSV line.
now the functions like strip! chomp! et. all return nil if the string was not modified
"abc".strip! # => nil
" abc ".strip! # => "abc"
What is the Ruby way to say trim it if it contains extra leading or trailing spaces without creating copies?
Gets uglier if I want to do tokens[Title].chomp!.strip!
I guess what you want is:
#title = tokens[Title]
#title.strip!
The #strip! method will return nil if it didn't strip anything, and the variable itself if it was stripped.
According to Ruby standards, a method suffixed with an exclamation mark changes the variable in place.
Update: This is output from irb to demonstrate:
>> #title = "abc"
=> "abc"
>> #title.strip!
=> nil
>> #title
=> "abc"
>> #title = " abc "
=> " abc "
>> #title.strip!
=> "abc"
>> #title
=> "abc"
Btw, now ruby already supports just strip without "!".
Compare:
p "abc".strip! == " abc ".strip! # false, because "abc".strip! will return nil
p "abc".strip == " abc ".strip # true
Also it's impossible to strip without duplicates. See sources in string.c:
static VALUE
rb_str_strip(VALUE str)
{
str = rb_str_dup(str);
rb_str_strip_bang(str);
return str;
}
ruby 1.9.3p0 (2011-10-30) [i386-mingw32]
Update 1:
As I see now -- it was created in 1999 year (see rev #372 in SVN):
Update2:
strip! will not create duplicates — both in 1.9.x, 2.x and trunk versions.
There's no need to both strip and chomp as strip will also remove trailing carriage returns - unless you've changed the default record separator and that's what you're chomping.
Olly's answer already has the canonical way of doing this in Ruby, though if you find yourself doing this a lot you could always define a method for it:
def strip_or_self!(str)
str.strip! || str
end
Giving:
#title = strip_or_self!(tokens[Title]) if tokens[Title]
Also keep in mind that the if statement will prevent #title from being assigned if the token is nil, which will result in it keeping its previous value. If you want or don't mind #title always being assigned you can move the check into the method and further reduce duplication:
def strip_or_self!(str)
str.strip! || str if str
end
As an alternative, if you're feeling adventurous you can define a method on String itself:
class String
def strip_or_self!
strip! || self
end
end
Giving one of:
#title = tokens[Title].strip_or_self! if tokens[Title]
#title = tokens[Title] && tokens[Title].strip_or_self!
If you are using Ruby on Rails there is a squish
> #title = " abc "
=> " abc "
> #title.squish
=> "abc"
> #title
=> " abc "
> #title.squish!
=> "abc"
> #title
=> "abc"
If you are using just Ruby you want to use strip
Herein lies the gotcha.. in your case you want to use strip without the bang !
while strip! certainly does return nil if there was no action it still updates the variable so strip! cannot be used inline. If you want to use strip inline you can use the version without the bang !
strip! using multi line approach
> tokens["Title"] = " abc "
=> " abc "
> tokens["Title"].strip!
=> "abc"
> #title = tokens["Title"]
=> "abc"
strip single line approach... YOUR ANSWER
> tokens["Title"] = " abc "
=> " abc "
> #title = tokens["Title"].strip if tokens["Title"].present?
=> "abc"
If you want to use another method after you need something like this:
( str.strip || str ).split(',')
This way you can strip and still do something after :)
I think your example is a sensible approach, although you could simplify it slightly as:
#title = tokens[Title].strip! || tokens[Title] if tokens[Title]
Alternative you could put it on two lines:
#title = tokens[Title] || ''
#title.strip!
If you have either ruby 1.9 or activesupport, you can do simply
#title = tokens[Title].try :tap, &:strip!
This is really cool, as it leverages the :try and the :tap method, which are the most powerful functional constructs in ruby, in my opinion.
An even cuter form, passing functions as symbols altogether:
#title = tokens[Title].send :try, :tap, &:strip!
My way:
> (#title = " abc ").strip!
=> "abc"
> #title
=> "abc"
#title = tokens[Title].strip! || tokens[Title]
It's entirely possible i'm not understanding the topic, but wouldn't this do what you need?
" success ".strip! || "rescue" #=> "success"
"failure".strip! || "rescue" #=> "rescue"

Remove a character at an index position in Ruby

Basically what the question says. How can I delete a character at a given index position in a string? The String class doesn't seem to have any methods to do this.
If I have a string "HELLO" I want the output to be this
["ELLO", "HLLO", "HELO", "HELO", "HELL"]
I do that using
d = Array.new(c.length){|i| c.slice(0, i)+c.slice(i+1, c.length)}
I dont know if using slice! will work here, because it will modify the original string, right?
Won't Str.slice! do it? From ruby-doc.org:
str.slice!(fixnum) => fixnum or nil [...]
Deletes the specified portion from str, and returns the portion deleted.
If you're using Ruby 1.8, you can use delete_at (mixed in from Enumerable), otherwise in 1.9 you can use slice!.
Example:
mystring = "hello"
mystring.slice!(1) # mystring is now "hllo"
# now do something with mystring
$ cat m.rb
class String
def maulin! n
slice! n
self
end
def maulin n
dup.maulin! n
end
end
$ irb
>> require 'm'
=> true
>> s = 'hello'
=> "hello"
>> s.maulin(2)
=> "helo"
>> s
=> "hello"
>> s.maulin!(1)
=> "hllo"
>> s
=> "hllo"
To avoid needing to monkey patch String you can make use of tap:
"abc".tap {|s| s.slice!(2) }
=> "ab"
If you need to leave your original string unaltered, make use of dup, eg. abc.dup.tap.
I did something like this
c.slice(0, i)+c.slice(i+1, c.length)
Where c is the string and i is the index position I want to delete. Is there a better way?

Resources