Ruby: How to Find Out If a Character Is a Letter or a Digit

Ruby: How to find out if a character is a letter or a digit?

Use a regular expression that matches letters & digits:

def letter?(lookAhead)
lookAhead.match?(/[[:alpha:]]/)
end

def numeric?(lookAhead)
lookAhead.match?(/[[:digit:]]/)
end

These are called POSIX bracket expressions, and the advantage of them is that unicode characters under the given category will match. For example:

'ñ'.match?(/[A-Za-z]/)     #=> false
'ñ'.match?(/\w/) #=> false
'ñ'.match?(/[[:alpha:]]/) #=> true

You can read more in Ruby’s docs for regular expressions.

Doesn't Ruby have isalpha?

There's a special character class for this:

char.match(/^[[:alpha:]]$/)

That should match a single alphabetic character. It also seems to work for UTF-8.

To test a whole string:

string.match(/^[[:alpha:]]+$/)

Keep in mind this doesn't account for spaces or punctuation.

If equal to a letter

Rewritten

def letter(str)
str.each_char.map do |char|
(char =~ /[[:alpha:]]/) ? 'bug' : 'ant'
end
end

In your code, you are trying to print "bug" or "ant"; but you're returning (0..str.length).to_a. This function will return an array of bugs and ants. It is also made more Rubyish:

  • methods should be in snake_case (lowercase, with underscores between words)
  • iterating over strings is easier with each_char
  • it's fine with [A-Za-z], but [[:alpha:]] is both clearer and handles Unicode stuff.
  • since we're testing each character, you know it's going to be one character long, so you don't need the start of line and end of line anchors.

How to check if given username has at least one letter in ruby

As I understand you want to determine if the string has only letters and numbers and at least one letter. You could use the following regular expression:

r = /\A\p{Alnum}*\p{L}\p{Alnum}*\z/

This reads, "match a start-of-string anchor, followed by zero or more alphanumeric (Unicode) characters (letters or numbers), followed by a letter, followed by zero or more alphanumeric characters, followed by an end-of-string anchor".

"12abc34".match?(r) #=> true
"1234567".match?(r) #=> false
"=12abc3".match?(r) #=> false
"".match?(r) #=> false

Another way:

r = /\A(?=.*\p{L})\p{Alnum}*\z/

This reads, "match a start-of-string anchor, followed by a letter preceded by zero or more of characters, in a positive lookahead (which consumes no characters), followed by zero or more alphanumeric characters, followed by an end-of-string anchor".

In Ruby, can I check if a string contains a letter without using regular expressions?

Try this

str.count("a-zA-Z") > 0

The count function accepts character sets as argument.

This might still fail with ArgumentError: invalid byte sequence in UTF-8 though. If your input is invalid there is likely no way around fixing the encoding.

NB, this scans the entire string, but so does downcase. For a performance benchmark see Eric's answer, performance varies a lot between worst case and best case scenario. As always though, readability comes before premature optimization.

Detect characters in a string

Let n be the number of letters in the input and m be the number of letters in the alphabet.


input.scan(/[a-zA-Z]/).uniq.join

is O(n) + O(n) + O(n). Fortunately, you are doing this only once (when what the pattern to gsub is evaluated) Therefore, your complexity adds up to 2*O(m) + 3*O(n) + O(m) = O(max(n, m)).


On the other hand,

input.downcase.include?(letter)

is O(n), but it is executed for each letter in the alphabet, leaving you with O(m*n) + O(m) = O(m*n).


Therefore, the first solution is asymptotically better, as O(max(n, m)) < O(m*n).

That is unless you consider the number of letters in the alphabet a small constant, in which case they are both O(n) and it's just a matter of benchmarking.

You can see that both are linear:

With regex; first solution

No regex; second solution

Running 100_000 iterations on a random 1000 letter string gave the following results (using cruby 2.2.2):

       user     system      total        real
36.160000 0.000000 36.160000 ( 36.182512)
3.910000 0.000000 3.910000 ( 3.915191)

So in practice, the second solution is far superior.

It is also way more readable.

Check if a string contains only digits in ruby

You can try the following

def check_string(string)
string.scan(/\D/).empty?
end

It would be truthy if string contains only digits or if it is an empty string. Otherwise returns false.

Check if string contains only permitted characters

Using positive lookahead:

pattern = /^(?=.*\D)[-\w]+$/

pattern =~ 'qwerty'
# => 0
pattern =~ 'identifier-45'
# => 0
pattern =~ 'u_-_-'
# => 0
pattern =~ '-42-'
# => 0

pattern =~ '123456'
# => nil
pattern =~ 'w&1234'
# => nil
pattern =~ 'identifier 42'
# => nil

how to return true or false when a string contains any letters A-Z or a-z?

I think, you can try something like it:

def letters?(string)
string.chars.any? { |char| ('a'..'z').include? char.downcase }
end

If you don't wanna use regexp. This method return true if there are any letters in the string:

> letters? 'asd'
=> true
> letters? 'asd123'
=> true
> letters? '123'
=> false

Ruby on Rails Strings: Find next character that is not a letter or number?

You should use a regular expression to parse/extract the user references:

# Transform comment content inline.
@comment.content.gsub!(/@[\w\d]+/) {|user_ref| link_if_user_reference(user_ref) }
@comment.save!

# Helper to generate a link to the user, if user exists
def link_if_user_reference(user_ref)
username = user_ref[1..-1]
return user_ref unless User.find_by_name(username)

link_to user_ref, "/users/#{user_name}"
# => produces link @username => /user/username
end

This assumes your usernames are restricted to alphanumeric characters as you said (letters or numbers). If you have other characters, you can add them to the set included in your regular expression.



Related Topics



Leave a reply



Submit