Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
76 views
in Technique[技术] by (71.8m points)

How to skip over whitespaces in .map. Ruby

This is my code:

def weirdcase (string)
  string.chars.map.with_index { |letter, index|
    unless index.odd?;
      letter = letter.upcase
    else
      letter
    end }.compact.join("")
end

This is what it's supposed to do:

"ThIs Is A TeSt"

And this is what I got:

"ThIs iS A TeSt"

It's giving me the wrong string in return because it's counting/including the white spaces in my code. All I need to do is find a way to skip the white spaces then I'm good to go. Thanks!

question from:https://stackoverflow.com/questions/65948008/how-to-skip-over-whitespaces-in-map-ruby

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem

I assume that the objective is to capitalize, for each word, all letters at even indices (the first letter of the word having index zero).

Here are two ways to do that. Both methods use String#gsub with a regular expression. Depending on requirements it may be necessary to change str.gsub... to str.downcase.gsub... for both methods.

Use a regular expression to match one- or two-characters strings, two if possible, and capitalize those strings.

def weirdcase(str)
  str.gsub(/(?<=A| |[^ ]{2})[^ ]{1,2}/) { |s| s.capitalize } 
end
weirdcase "this is a sentence for    testing"
  #=> "ThIs Is A SeNtEnCe FoR    TeStInG"

The regular expression reads, "match one or two characters other than spaces, two if possible ([^ ]{1,2}), that are immediately preceded by one of the following: the beginning of the string (A), a space or two characters other than spaces. (?<=A| |[^ ]{2}) is a positive lookbehind.

s.capitalize invokes the method String#capitalize on the match.

Use a cycling enumerator

def weirdcase(str)
  enum = [:upcase, :downcase].cycle
  str.gsub(/./) do |s|
    if s == ' '
      enum.rewind
      ' '
    else
      s.public_send(enum.next)
    end
  end
end
weirdcase "this is a sentence for testing"
  #=> "ThIs Is A SeNtEnCe FoR TeStInG"

The regular expression /./ matches each character in the string.

See Array#cycle, Enumerator#rewind, Enumerator#next and Object#public_send.

Note the following.

enum = [:upcase, :downcase].cycle
  #=> #<Enumerator: [:upcase, :downcase]:cycle>
enum.next
  #=> :upcase
enum.next
  #=> :downcase
enum.next
  #=> :upcase                       
enum.rewind
  #=> #<Enumerator: [:upcase, :downcase]:cycle>
enum.next
  #=> :upcase
enum.next
  #=> :downcase
... ad infinitum

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...