beaconhill
beaconhill

Reputation: 451

Rails string split every other "."

I have a bunch of sentences that I want to break into an array. Right now, I'm splitting every time \n appears in the string.

@chapters = @script.split('\n')

What I'd like to do is .split ever OTHER "." in the string. Is that possible in Ruby?

Upvotes: 1

Views: 63

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110665

This is a case where it's easier to use String#scan than String#split.

We can use the following regular expression:

r = /(?<=\.|\A)[^.]*\.[^.]*(?=\.|\z)/
str=<<~_
Now is the time. This is it. It is now. The time to have fun.
The time to make new friends. The time to party.
_
str.scan(r)
  #=> [
  #    "Now is the time. This is it",
  #    " It is now. The time to have fun",
  #    "\nThe time to make new friends. The time to party"
  #=> ]

We can write the regular expression in free-spacing mode to make it self-documenting.

r = /
    (?<=     # begin a positive lookbehind
      \A     # match the beginning of the string
      |      # or
      \.     # match a period
    )        # end positive lookbehind
    [^.]*    # match zero or more characters other than periods
    \.       # match a period
    [^.]*    # match zero or more characters other than periods
    (?=      # begin a positive lookahead
      \.     # match a period
      |      # or
      \z     # match the end of the string
    )        # end positive lookahead
    /x       # invoke free-spacing regex definition mode

Note that (?<=\.|\A) can be replaced with (?<![^\.]). (?<![^\.]) is a negative lookbehind that asserts the match is not preceded by a character other than a period.

Similarly, (?=\.|\z) can be replaced with (?![^.]). (?![^.]) is a negative lookahead that asserts the match is not followed by a character other than a period.

Upvotes: 1

Chris Heald
Chris Heald

Reputation: 62638

You could do it with a regex, but I'd start with a simple approach: just split on periods, then join pairs of substrings:

s = "foo. bar foo. foo bar. boo far baz. bizzle"
s.split(".").each_slice(2).map {|p| p.join "." }
# => => ["foo. bar foo", " foo bar. boo far baz", " bizzle"]

Upvotes: 1

Related Questions