I have the following input string:
string = "\"Newegg.com\" <Promo#email.newegg.com>"
I want to replace the \" with \'. I tried this:
string.gsub(/\"/) {|i| "\\'" }
# => "\\'Newegg.com\\' <Promo#email.newegg.com>"
string.gsub(/\"/,%q(\\\'))
# => "\\'Newegg.com\\' <Promo#email.newegg.com>"
In both ways, it actually has two instances of \, but I want only one. It seems to be an issue with the backslash and escaping b/c this works otherwise:
string.gsub(/\"/,%q('))
# => "'Newegg.com' <Promo#email.newegg.com>"
-- Update 1--
yes, puts does display the "correct" value
temp = string.gsub(/\"/,%q(\\\'))
# => "\\'Newegg.com\\' <Promo#email.newegg.com>"
puts temp
# >> \'Newegg.com\' <Promo#email.newegg.com>
but I want to store this exact value displayed on the last line.
Your actual string doesn't include \
puts "\"Newegg.com\" <Promo#email.newegg.com>"
> "Newegg.com" <Promo#email.newegg.com>
This will replace " with ' as you wished:
puts "\"Newegg.com\" <Promo#email.newegg.com>".gsub('"', "'")
> 'Newegg.com' <Promo#email.newegg.com>
If you really wanted \", try another escape character like:
puts "\\\"Newegg.com\\\" <Promo#email.newegg.com>"
> \"Newegg.com\" <Promo#email.newegg.com>
Same replace should work:
puts "\\\"Newegg.com\\\" <Promo#email.newegg.com>".gsub('"', "'")
> \'Newegg.com\' <Promo#email.newegg.com>
Looks like your getting a bit confused (understandably so) by the returned result.
Keep in mind that in irb, the last result is formatted using .inspect, which means that it wraps strings in double quotes, and then escapes characters (backslashes and double quotes)' that would need to be escaped in a double quoted string. This is to distinguish between strings and other values such as numbers, arrays, hashes, etc.
However, that is just the result of inspect. if you use puts to output the value, it will output it without any escaping - it is a more accurate representation of your value.The value displayed by puts is the real value, and what would be stored if you saved the value to a variable.
If you still can't tell what your string looks like, try this:
temp = string.gsub(/\"/,%q(\\\'))
temp.split('')
=> ["\\", "'", "N", "e", "w", "e", "g", "g", ".", "c", "o", "m", "\\", "'", " ", "<", "P", "r", "o", "m", "o", "#", "e", "m", "a", "i", "l", ".", "n", "e", "w", "e", "g", "g", ".", "c", "o", "m", ">"]
This explodes your string into an array of single characters, and can make it easier to see exactly what is in your string. Notice you have a \ character (displayed as "\\", but since each string is guaranteed to be exactly one character long, you know it is being displayed that way because of inspect) and a ' character at the beginning.
I have the following (working) code I'm trying to convert into a more concise snippet using either #map or #select.
def duplicate_string(string)
s_list = []
string.downcase.chars.each do |char|
if string.index(char) != string.rindex(char) && s_list.include?(char) == false
s_list << char if char != ' '
end
end
s_list
end
puts duplicate_string("I am a duplicate string") == ["i", "a", "t"] #true
This is what I've come up with so far, but I don't know how to access the current array that's been stored by #map or #select and using self isn't working
def duplicate_string_with_map(string)
string.downcase.chars.select { |char| string.index(char) != string.rindex(char) && self.include?(char) == false && char != ' ' }
end
The following code would solve your purpose:
def duplicate_string_with_map(string)
(string.downcase.chars.select { |char| string.index(char) != string.rindex(char) && char != ' ' }).uniq
end
Here you need not check include condition as you are already ensuring string.index(char) != string.rindex(char).
However, for a better ruby approach, I would suggest you to re-open String class and write a method there.
It would look something like this:
class String
def duplicate_characters_array
(downcase.chars.select { |char| index(char) != rindex(char) && char != ' ' }).uniq
end
end
string = "I am a duplicate string"
string.duplicate_characters_array
You don't need to access the array and you don't need to use Array#map.
There are many ways to reach the goal. One of them is to split the string in chars then group the chars (get a hash), reject the groups of space character and the groups smaller than two elements and return the keys of the remaining groups:
"I am a duplicate string"
.downcase
.chars
.group_by{|i| i}
.reject{|k, v| k == ' ' || v.length < 2}
.keys
# ["a", "i", "t"]
Here we can make use of a helper method, Array#difference. The method is explained here. Note that that link contains a link to an SO answer where I cite examples of its use. Though I proposed that the method be added to the Ruby core there appears to be little interest in doing so.
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
Here we can use this helper as follows.
def duplicate_string(str)
a = str.gsub(/\s/,'').downcase.reverse.chars
a.difference(a.uniq).uniq.reverse
end
duplicate_string "I am a duplicate string"
#=> ["a", "i", "t"]
The steps are as follows.
str = "I am a duplicate string"
b = str.gsub(/\s/,'')
#=> "Iamaduplicatestring"
c = b.downcase
#=> "iamaduplicatestring"
d = c.reverse
#=> "gnirtsetacilpudamai"
a = d.chars
#=> ["g", "n", "i", "r", "t", "s", "e", "t", "a", "c", "i", "l", "p",
# "u", "d", "a", "m", "a", "i"]
e = a.uniq
#=> ["g", "n", "i", "r", "t", "s", "e", "a", "c", "l", "p", "u", "d", "m"]
f = a.difference(e)
#=> ["t", "i", "a", "a", "i"]
g = f.uniq
#=> ["t", "i", "a"]
g.reverse
#=> ["a", "i", "t"]
The key step is the calculation of f. For each element c of e, f contains n-1 instances of c, where n is the number of instances of c in a. The method therefore excludes characters other than spaces that appear in the string exactly once.
I've came across a weird thing doing simple tasks in Ruby. I just want to iterate the alphabet with the each method but the iteration goes first in the execution:
alfawit = ("a".."z")
puts "That's an alphabet: \n\n #{ alfawit.each { |litera| puts litera } } "
and this code results in this: (abbreviated)
a
b
c
⋮
x
y
z
That's an alphabet:
a..z
Any ideas why it works like this or what supposedly I did wrong?
Thanks in advance.
Because your each call is interpolated in your string literal that's executed before the fixed string. Also, each returns an Enumerable, in fact you print even that. Try this one
alfawit = ("a".."z")
puts "That's an alphabet: \n\n"
alfawit.each { |litera| puts litera }
or
puts "That's an alphabet: \n\n"
("a".."z").each { |litera| puts litera }
you can use interpolation if you want but in this way
alfawit = ("a".."z")
puts "That's an alphabet: \n\n#{alfawit.to_a.join("\n")}"
You can easily see what's going on if you extract the interpolation part into a variable:
alfawit = ("a".."z")
foo = alfawit.each { |litera| puts litera }
puts "That's an alphabet: \n\n #{ foo } "
The second line is causing the trouble: each invokes the block for each element of the range and then returns the receiver, so that foo becomes alfawit.
Here's another way to get the desired result:
alfawit = "a".."z"
puts "That's an alphabet:", alfawit.to_a
puts outputs each argument on a new line, but for array arguments, it outputs each element on a new line. Result:
That's an alphabet:
a
b
c
⋮
x
y
z
Likewise, you can turn the range into an argument list via *:
alfawit = "a".."z"
puts "That's an alphabet:", *alfawit
That's equivalent to:
puts "That's an alphabet:", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
I'm very new to ruby at the moment but I came from a PHP background and must say that I enjoy doing ruby, alot. It's a really nice language and the community is strict but helpful.
Today I was looking at stackoverflow and checked one of my answers to a question to generate a random string using PHP. I had actually written a script for this so I thought, why not share it!
This script has some modifiers which allow you to choose wether you want to include the following sets
lowercase a-z
[1] + uppercase a-z
[1, 2] + numbers
[1, 2, 3] + special characters
[1, 2, 3, 4] + some crazy voodooh characters
So in this PHP script I physically typed each set into an array e.g.:
$charSubSets = array(
'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789',
'!##$%^&*()_+{}|:">?<[]\\\';,.`~',
'µñ©æáßðøäåé®þüúíóö'
);
and this was basically my way of being able to define complexity right there.
Now this looks alright, even in the code but ruby has ranges and ranges are something new and shiny for me to play with so I was thinking of building a random string generator later today just to get some more experience with it.
Now for my question, I know that you can do the following things with a range including:
'a'..'z'
'A'..'Z'
0..9
etc.. But I was thinking, could you also make a range with special characters? as in, only special characters? and if that is possible, would you also be able to do the same for the crazy voodooh?
The reason I'm asking is because there is no example in the docs or anything on SO explaining this.
Check out Range#to_a which is gotten from Enumerable. Note that on the left hand side of the docs it says that Range includes Enumerable, which means that the methods in Enumerable can be called on Ranges. If you can't find a method in a class, see what modules the docs say are included and click on the link to the included module.
Check out Array#shuffle.
Check out Array#join
Check out Array#[], which will take a range as a subscript, so you can take a slice of an array of random characters.
A two dot Range includes the end. A three dot Range doesn't include the end:
p (1...5).to_a #=> [1, 2, 3, 4]
Putting it all together:
chars = (0..9).to_a + ('A'..'z').to_a + ('!'..'?').to_a
10.times do
puts chars.shuffle[0..5].join
end
--output:--
I(m,E.
%_;i(3
rb=_ef
kJrA9n
YA`e.K
89qCji
Ba1x3D
acp)=8
2paq3I
U0>Znm
(Shakespeare will appear there eventually.)
Yes - this is certainly possible.
Fire up your console e.g. irb or pry.
1. for the special characters:
('!'..'?').to_a
# => [
# "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-",
# ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":",
# ";", "<", "=", ">", "?"
# ]
2. for the 'voodooh' characters:
('µ'..'ö').to_a
# => [
# "µ", "¶", "·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", "À", "Á",
# "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î",
# "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö"
# ]
This is trivial to just try tho, the position (and kb index of the key) on your keyboard for the end special character defines what characters come inbetween, if I'd pick a ~ instead of a ? for the end it would look like this:
('!'..'~').to_a
# => [
# "`", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",",
# "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
# ":", ";", "<", "=", ">", "?", "#", "A", "B", "C", "D", "E", "F",
# "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
# "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "a",
# "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
# "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{",
# "|", "}", "~"
# ]
basically if character a is 65 and z is 90 then all characters inbetween like b which is 66 will be included, it works like that for anything you put in a range and since in ruby everything is an object, you can use anything in a range as long as it implements certain methods as explained by the docs!
EDIT (13-11-2015)
After doing some playing around in my console I came to this solution which "mimics" the given PHP example and perhaps even completes it.
def rng(length = 10, complexity = 4)
subsets = [("a".."z"), ("A".."Z"), (0..9), ("!".."?"), ("µ".."ö")]
chars = subsets[0..complexity].map { |subset| subset.to_a }.flatten
# => [
# "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
# "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
# "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
# "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
# "W", "X", "Y", "Z", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "!", "\"",
# "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".",
# "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":",
# ";", "<", "=", ">", "?", "µ", "¶", "·", "¸", "¹", "º", "»",
# "¼", "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç",
# "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó",
# "Ô", "Õ", "Ö"
# ]
chars.sample(length).join
end
Now calling rng will produce results like this:
rng # => "·boÇE»Ñ¼Á¸"
rng(10, 2) # => "nyLYAsxJi9"
rng(20, 2) # => "EOcQdjZa0t36xCN8TkoX"
EDIT#2 (14-05-2020)
As pointed out below in the comments, I did not even provide a documentation link to the relevant concept, in Ruby this is called a Range and can be found here (2.5.0).
If you need docs for your specific version, try googling for ruby range [your ruby version]. You can find out what your version is by running ruby -v in the terminal. Happy rubying :D
all dates are in dd-mm-yyyy format
I am trying to validate strings in ruby.
Any string which contains spaces,under scores or any special char should fail validation.
The valid string should contain only chars a-zA-Z0-9
My code looks like.
def validate(string)
regex ="/[^a-zA-Z0-9]$/
if(string =~ regex)
return "true"
else
return "false"
end
I am getting error:
TypeError: type mismatch: String given.
Can anyone please let me know what is the correct way of doing this?
If you are validating a line:
def validate(string)
!string.match(/\A[a-zA-Z0-9]*\z/).nil?
end
No need for return on each.
You can just check if a special character is present in the string.
def validate str
chars = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
str.chars.detect {|ch| !chars.include?(ch)}.nil?
end
Result:
irb(main):005:0> validate "hello"
=> true
irb(main):006:0> validate "_90 "
=> false
def alpha_numeric?(char)
if (char =~ /[[:alpha:]]/ || char =~ /[[:digit:]]/)
true
else
false
end
end
OR
def alpha_numeric?(char)
if (char =~ /[[:alnum:]]/)
true
else
false
end
end
We are using regular expressions that match letters & digits:
The above [[:alpha:]] ,[[:digit:]] and [[:alnum:]] are POSIX bracket expressions, and they have the advantage of matching Unicode characters in their category. Hope this helps.
checkout the link below for more options:
Ruby: How to find out if a character is a letter or a digit?
No regex:
def validate(str)
str.count("^a-zA-Z0-9").zero? # ^ means "not"
end
Great answers above but just FYI, your error message is because you started your regex with a double quote ". You'll notice you have an odd number (5) of double quotes in your method.
Additionally, it's likely you want to return true and false as values rather than as quoted strings.
Similar to the very efficient regex-ish approach mentioned already by #steenslag and nearly just as fast:
str.tr("a-zA-Z0-9", "").length.zero?
OR
str.tr("a-zA-Z0-9", "") == 0
One benefit of using tr though is that you could also optionally analyze the results using the same basic formula:
str = "ABCxyz*123$"
rejected_chars = str.tr("a-zA-Z0-9", "")
#=> *$
is_valid = rejected_chars.length.zero?
#=> false
Similar to #rohit89:
VALID_CHARS = [*?a..?z, *?A..?Z, *'0'..'9']
#=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
# "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
# "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
# "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
# "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
def all_valid_chars?(str)
a = str.chars
a == a & VALID_CHARS
end
all_valid_chars?('a9Z3') #=> true
all_valid_chars?('a9 Z3') #=> false
Use .match? in Ruby 2.4+.
Ruby 2.4 introduced a convenient boolean-returning .match? method.
In your case, I would do something like this:
# Checks for any characters other than letters and numbers.
# Returns true if there are none. Returns false if there are one or more.
#
def valid?( string )
!string.match?( /[^a-zA-Z0-9]/ ) # NOTE: ^ inside [] set turns it into a negated set.
end