Help me condence my code?

I know this could be more idiomatic to ruby.

it's basically to turn http://www.gutenberg.org/etext/18362 into an
array. the "_no_extras" refers to me having snipped the intro and
outro of the text outside of ruby. I still have to do something with
the "SECTION" fields and the "A", "B", etc. fields. (not to mention
some kind of linguistic parsing which would make f[rand(f.size)] + " "
f[rand(f.size)] + " " .... link together in a coherent matter, but
that's a little beyond me. any direction in this area would be kindly
appreciated though! I'm thinking of separating it into different text
files maybe. certain sections are almost whole sentences, they're
grouped in all kinds of ways that will maybe help with this. no
long-term goal, really, just learning ruby and having fun. :slight_smile:

anyhow, the sloppy newbie code is as follows:

f = File.read("phrases_no_extra.txt")
f = f.to_a
f = f.each { |x| x.chop! }
f.each_with_index { |x,y| # deletes the empty array items
  if x.size == 0
    f.delete_at(y)
  end
  }
f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
  if x.include? "]" # of his comments
    f.delete_at(y)
  end
  }
f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
  if x.include? "["
    f.delete_at(y)
  end
  }
f.delete_at(-1) # random whitespace item at the end from the last quote
  
puts f[rand(f.size)]

Simon Schuster wrote:

I know this could be more idiomatic to ruby.

it's basically to turn Fifteen Thousand Useful Phrases by Grenville Kleiser | Project Gutenberg into an
array. the "_no_extras" refers to me having snipped the intro and
outro of the text outside of ruby. I still have to do something with
the "SECTION" fields and the "A", "B", etc. fields. (not to mention
some kind of linguistic parsing which would make f[rand(f.size)] + " "
f[rand(f.size)] + " " .... link together in a coherent matter, but
that's a little beyond me. any direction in this area would be kindly
appreciated though! I'm thinking of separating it into different text
files maybe. certain sections are almost whole sentences, they're
grouped in all kinds of ways that will maybe help with this. no
long-term goal, really, just learning ruby and having fun. :slight_smile:

anyhow, the sloppy newbie code is as follows:

f = File.read("phrases_no_extra.txt")
f = f.to_a
f = f.each { |x| x.chop! }
f.each_with_index { |x,y| # deletes the empty array items
  if x.size == 0
    f.delete_at(y)
  end
  }
f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
  if x.include? "]" # of his comments
    f.delete_at(y)
  end
  }
f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
  if x.include? "["
    f.delete_at(y)
  end
  }
f.delete_at(-1) # random whitespace item at the end from the
last quote

puts f[rand(f.size)]

ok, here's my first shot at a newbie to programming trying to solve
something like this. I hope this works for what you are trying to do. I
wish I would have had an example to play with before posting, but oh
well. I can only learn from this as well right? well here goes...

f = IO.readlines("phrases_no_extra.txt").each_with_index do |x, y|
  if x.chop!.size.eql?(0)
    f.delete_at(y)
  end
  if x.include?("]") or x.include?("[")
    f.delete_at(y)
  end
end.delete_at(-1)
puts f[rand(f.size)]

let me know how it goes!

~Jeremy

···

--
Posted via http://www.ruby-forum.com/\.

Simon Schuster wrote:

anyhow, the sloppy newbie code is as follows:

Write unit tests for it, then refactor it, one tiny change at a time, passing all the tests after each change. If the tests fail, undo the change.

···

--
  Phlip
  Test Driven Ajax (on Rails) [Book]
  "Test Driven Ajax (on Rails)"
  assert_xpath, assert_javascript, & assert_ajax

Simon Schuster wrote:

I know this could be more idiomatic to ruby.

Don't know about idiomatic, but here's my
filter-split-filter take:

  require 'open-uri'

  f = open('http://www.gutenberg.org/files/18362/18362.txt'\).read.
      gsub(/\s*\[.*?\]/m,''). # strip comments
      split("\r\n"). # DOS line endings
      delete_if{ |e| e.empty? } # remove blank lines

  puts f[ rand f.size ]

Regards,

···

--
Bil Kleb
http://nasarb.rubyforge.org

The main problem is that you loop through the Array four separate times first to chop, then to remove empty lines and then twice to remove comments. There is no reason why you can't combine them. Perhaps this is a good example to learn how to use 'or', 'and' and 'not':

f =

IO.readlines("phrases_no_extra.txt").each do |l|
   l.chop!
   f << l if l.size != 0 and not (l.include?("]") or l.include?("["))
end

puts f[rand(f.size)]

Alex Gutteridge

Bioinformatics Center
Kyoto University

···

On 7 Sep 2007, at 09:29, Simon Schuster wrote:

anyhow, the sloppy newbie code is as follows:

f = File.read("phrases_no_extra.txt")
f = f.to_a
f = f.each { |x| x.chop! }
f.each_with_index { |x,y| # deletes the empty array items
  if x.size == 0
    f.delete_at(y)
  end
  }
f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
  if x.include? "]" # of his comments
    f.delete_at(y)
  end
  }
f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
  if x.include? "["
    f.delete_at(y)
  end
  }
f.delete_at(-1) # random whitespace item at the end from the last quote
  
puts f[rand(f.size)]

While this does not handle everything in the input stream you mention,
This will print most of the lines you are looking for. This will skip
blank lines and lines with whose only content is a single upper case
letter. This will also remove the full and partial comments following
a phrase. With some work on the regular expressions it could probably
do what you want. This solution has the advantages of not reading the
entire input stream into memory before processing and of being
concise. It has the disadvantage of requiring Rio (http://
rio.rubyforge.org) which is not part of the standard ruby library.

require 'rio'

rio('phrases_no_extra.txt').chomp.lines(/^\S/).skip(/^[A-Z]?$/) do |
line>
  puts line.gsub(/\s+\[.*$/,'')
end

···

On Sep 6, 5:29 pm, "Simon Schuster" <significa...@gmail.com> wrote:

I know this could be more idiomatic to ruby.

it's basically to turnhttp://www.gutenberg.org/etext/18362into an
array. the "_no_extras" refers to me having snipped the intro and
outro of the text outside of ruby. I still have to do something with
the "SECTION" fields and the "A", "B", etc. fields. (not to mention
some kind of linguistic parsing which would make f[rand(f.size)] + " "
f[rand(f.size)] + " " .... link together in a coherent matter, but
that's a little beyond me. any direction in this area would be kindly
appreciated though! I'm thinking of separating it into different text
files maybe. certain sections are almost whole sentences, they're
grouped in all kinds of ways that will maybe help with this. no
long-term goal, really, just learning ruby and having fun. :slight_smile:

anyhow, the sloppy newbie code is as follows:

f = File.read("phrases_no_extra.txt")
f = f.to_a
f = f.each { |x| x.chop! }
f.each_with_index { |x,y| # deletes the empty array items
        if x.size == 0
                f.delete_at(y)
        end
        }
f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
        if x.include? "]" # of his comments
                f.delete_at(y)
        end
        }
f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
        if x.include? "["
                f.delete_at(y)
        end
        }
f.delete_at(-1) # random whitespace item at the end from the last quote

puts f[rand(f.size)]

Ok, I'm going to try break this down a bit more than the other answers.
Simon Schuster wrote:

f = File.read("phrases_no_extra.txt")
f = f.to_a

f = IO.readlines("phrases_no_extra.txt")

f = f.each { |x| x.chop! }

Your "f =" at the start of this line does nothing. You'd be better off with either:

     f.each {|x| x.chop! }

or I prefer:

     f.map! {|x| x.chop }

f.each_with_index { |x,y| # deletes the empty array items
  if x.size == 0
    f.delete_at(y)
  end
  }

For starters, I don't think each_with_index will be stable if you delete elements in the middle of the block, so this probably won't work the way you want it to.

That and there's a convenient predicate for testing emptiness of strings.

Much better would be:

      f.delete_if {|x| x.empty? }

f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
  if x.include? "]" # of his comments
    f.delete_at(y)
  end
  }

     f.delete_if {|x| x.include("]") }

f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
  if x.include? "["
    f.delete_at(y)
  end
  }

     f.delete_if {|x| x.include("[") }

f.delete_at(-1) # random whitespace item at the end from the last quote

     f.pop

puts f[rand(f.size)]

Nothing wrong with this line. :slight_smile:

So, putting that all together and cleaning up a bit:

     f = IO.readlines("phrases_no_extra.txt").map {|x| x.chop }
     f.delete_if {|x| x.empty? || x.include?("[") || x.include?("]") }
     f.pop
     puts f[rand(f.size)]

That's pretty neat I think, but if you agree with Alex that looping over the array multiple times is a performance problem, then you should try something like:

     f =
     IO.each("phrases_no_extra.txt") do |x|
         x.chop!
         f << x unless x.empty? || x.include?("[") || x.include?("]")
     end
     f.pop
     puts f[rand(f.size)]

(This is an improvement over Alex's solution in that it doesn't read the entire file into memory at once. Rather it steps over the file reading a line at a time and only adding the ones you need to your array.)

Regards,

Pete Yandell

# anyhow, the sloppy newbie code is as follows:

be gentle to yourself. it is not sloppy. in fact i find it readable and it clearly shows what the code is trying to do (wc may not be what you want to do).. you can refactor it and put some tests as you go along.

# f = File.read("phrases_no_extra.txt")

on my case, i'd prefer that my programs do *not carry baggage of fixed static file names :slight_smile: this way, my program does not depend on that particular file, and i can use any file i want. try ARGF.

# f = f.to_a

you can combine that w the above like

   f = File.read("phrases_no_extra.txt").to_a

or you can use readlines to accomplish both, like,

   f = File.readlines("phrases_no_extra.txt")

now, your original code makes many passes to array f. you can do it one pass, and since delete_if accepts a block, you can do it like,

f.delete_if do |x|
   x.sub!(/\[.*/,"") # remove trailing comments
   x.sub!(/.*\].*/,"") # remove leading comments, they span multi lines
   x.strip! # remove leading/trailing whitespace
   x.empty?
end

note, we are also modifying the array as we move along..

thus combining w the above codes, you can futher condense it to

f = File.readlines("phrases_no_extra.txt").delete_if do |x|
      x.sub!(/\[.*/,"") # remove trailing comments
      x.sub!(/.*\].*/,"") # remove leading comments, they span multi lines
      x.strip! # remove leading/trailing whitespace
      x.empty?
    end

puts f[rand(f.size)]

you don't need the delete_at(-1) since (you said) it's a whitespace and will be taken care of by the code block.

using ARGF, you save chars, and your program is flexible, like

f = ARGF.to_a.delete_if do |x|
      x.sub!(/\[.*/,"") # remove trailing comments
      x.sub!(/.*\].*/,"") # remove leading comments
      x.strip! # remove leading/trailing whitespace
      x.empty?
    end
puts f[rand(f.size)]

_or_, if you have fear of those ! methods (like me), you can do

f = ARGF.to_a.delete_if do |x|
      x.replace x.sub(/\[.*/,"").sub(/.*\].*/,"").strip
      x.empty?
    end
puts f[rand(f.size)]

kind regards -botp

···

From: Simon Schuster [mailto:significants@gmail.com]

a = IO.read("phrases_no_extra.txt").
  split( /[\r?\n]+/ ).
  reject{|s|
    # Reject if length is less than 2 or if it contains
    # a [ or if it's composed entirely of upper case
    # letters and spaces.
    s.size < 2 or s.index "[" or s =~ /^[A-Z ]+$/ }

puts a[ rand( a.size ) ]

···

On Sep 6, 7:29 pm, "Simon Schuster" <significa...@gmail.com> wrote:

I know this could be more idiomatic to ruby.

it's basically to turnhttp://www.gutenberg.org/etext/18362into an
array. the "_no_extras" refers to me having snipped the intro and
outro of the text outside of ruby. I still have to do something with
the "SECTION" fields and the "A", "B", etc. fields. (not to mention
some kind of linguistic parsing which would make f[rand(f.size)] + " "
f[rand(f.size)] + " " .... link together in a coherent matter, but
that's a little beyond me. any direction in this area would be kindly
appreciated though! I'm thinking of separating it into different text
files maybe. certain sections are almost whole sentences, they're
grouped in all kinds of ways that will maybe help with this. no
long-term goal, really, just learning ruby and having fun. :slight_smile:

anyhow, the sloppy newbie code is as follows:

f = File.read("phrases_no_extra.txt")
f = f.to_a
f = f.each { |x| x.chop! }
f.each_with_index { |x,y| # deletes the empty array items
        if x.size == 0
                f.delete_at(y)
        end
        }
f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
        if x.include? "]" # of his comments
                f.delete_at(y)
        end
        }
f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
        if x.include? "["
                f.delete_at(y)
        end
        }
f.delete_at(-1) # random whitespace item at the end from the last quote

puts f[rand(f.size)]

puts IO.readlines("phrases_no_extra.txt").
  reject{|x| x =~ /\[|^[A-Z ]*$/}.
  instance_eval{ self[ rand(self.size) ] }

···

On Sep 6, 7:29 pm, "Simon Schuster" <significa...@gmail.com> wrote:

I know this could be more idiomatic to ruby.

it's basically to turnhttp://www.gutenberg.org/etext/18362into an
array. the "_no_extras" refers to me having snipped the intro and
outro of the text outside of ruby. I still have to do something with
the "SECTION" fields and the "A", "B", etc. fields. (not to mention
some kind of linguistic parsing which would make f[rand(f.size)] + " "
f[rand(f.size)] + " " .... link together in a coherent matter, but
that's a little beyond me. any direction in this area would be kindly
appreciated though! I'm thinking of separating it into different text
files maybe. certain sections are almost whole sentences, they're
grouped in all kinds of ways that will maybe help with this. no
long-term goal, really, just learning ruby and having fun. :slight_smile:

anyhow, the sloppy newbie code is as follows:

f = File.read("phrases_no_extra.txt")
f = f.to_a
f = f.each { |x| x.chop! }
f.each_with_index { |x,y| # deletes the empty array items
        if x.size == 0
                f.delete_at(y)
        end
        }
f.each_with_index { |x,y| # deleting all but the last (which is
spread of two lines)
        if x.include? "]" # of his comments
                f.delete_at(y)
        end
        }
f.each_with_index { |x,y| # yes, this is me unable to recall
how to do "or" hahaha.
        if x.include? "["
                f.delete_at(y)
        end
        }
f.delete_at(-1) # random whitespace item at the end from the last quote

puts f[rand(f.size)]

Jeremy Woertink wrote:

end.delete_at(-1)

OMG! You can call methods in an end??? I have lived far to long in the
scalar world! When would you do such a thing?

···

--
Posted via http://www.ruby-forum.com/\.

putting it into phrase-test.rb and running it that way I get:

ph-test.rb:3: undefined method `delete_at' for nil:NilClass (NoMethodError)
        from ph-test.rb:10:in `each_with_index'
        from ph-test.rb:1:in `each'
        from ph-test.rb:1:in `each_with_index'
        from ph-test.rb:1

and relatedly, going through step by step I get:

023:0> end.delete_at(-1)
SyntaxError: compile error
(irb):23: syntax error, unexpected kEND
end.delete_at(-1)

I've never seen tacking things onto end before! is this possible?

···

f = IO.readlines("phrases_no_extra.txt").each_with_index do |x, y|
  if x.chop!.size.eql?(0)
    f.delete_at(y)
  end
  if x.include?("]") or x.include?("[")
    f.delete_at(y)
  end
end.delete_at(-1)
puts f[rand(f.size)]

let me know how it goes!

~Jeremy
--
Posted via http://www.ruby-forum.com/\.

eek. I've never written a unit test before. that's all incredibly
murky territory.. not only am I new to ruby, but new to programming in
general. I'll get around to it someday, I think. it just seems scary.
:slight_smile:

···

On 9/6/07, Phlip <phlip2005@gmail.com> wrote:

Simon Schuster wrote:

> anyhow, the sloppy newbie code is as follows:

Write unit tests for it, then refactor it, one tiny change at a time,
passing all the tests after each change. If the tests fail, undo the change.

--
  Phlip
  Test Driven Ajax (on Rails) [Book]
  "Test Driven Ajax (on Rails)"
  assert_xpath, assert_javascript, & assert_ajax

my local copy has some extra (probably important) authorship/proj
gutenberg info at the beginning and end that I've stripped, but other
than that this code works perfectly. I really like how it's split up
by lines per method. thanks a lot!

also is \[ a literal bracket, or some kind of grouping device that
just happens to be also the boundary-character I'm looking for?

···

On 9/6/07, Bil Kleb <Bil.Kleb@nasa.gov> wrote:

Simon Schuster wrote:
> I know this could be more idiomatic to ruby.

Don't know about idiomatic, but here's my
filter-split-filter take:

  require 'open-uri'

  f = open('http://www.gutenberg.org/files/18362/18362.txt&#39;\).read.
      gsub(/\s*\[.*?\]/m,''). # strip comments
      split("\r\n"). # DOS line endings
      delete_if{ |e| e.empty? } # remove blank lines

  puts f[ rand f.size ]

Regards,
--
Bil Kleb
http://nasarb.rubyforge.org

That contained some redundancy.

a = IO.read("phrases_no_extra.txt").
  split( /[\r?\n]+/ ).
  reject{|s|
    # Reject if it contains a [ or if
    # it's composed entirely of upper case
    # letters and spaces.
    s.index "[" or s =~ /^[A-Z ]+$/ }

puts a[ rand( a.size ) ]

···

expandaf...@yahoo.com wrote:

On Sep 6, 7:29 pm, "Simon Schuster" <significa...@gmail.com> wrote:
> I know this could be more idiomatic to ruby.
>
> it's basically to turnhttp://www.gutenberg.org/etext/18362into an
> array. the "_no_extras" refers to me having snipped the intro and
> outro of the text outside of ruby. I still have to do something with
> the "SECTION" fields and the "A", "B", etc. fields. (not to mention
> some kind of linguistic parsing which would make f[rand(f.size)] + " "
> f[rand(f.size)] + " " .... link together in a coherent matter, but
> that's a little beyond me. any direction in this area would be kindly
> appreciated though! I'm thinking of separating it into different text
> files maybe. certain sections are almost whole sentences, they're
> grouped in all kinds of ways that will maybe help with this. no
> long-term goal, really, just learning ruby and having fun. :slight_smile:
>
> anyhow, the sloppy newbie code is as follows:
>
> f = File.read("phrases_no_extra.txt")
> f = f.to_a
> f = f.each { |x| x.chop! }
> f.each_with_index { |x,y| # deletes the empty array items
> if x.size == 0
> f.delete_at(y)
> end
> }
> f.each_with_index { |x,y| # deleting all but the last (which is
> spread of two lines)
> if x.include? "]" # of his comments
> f.delete_at(y)
> end
> }
> f.each_with_index { |x,y| # yes, this is me unable to recall
> how to do "or" hahaha.
> if x.include? "["
> f.delete_at(y)
> end
> }
> f.delete_at(-1) # random whitespace item at the end from the last quote
>
> puts f[rand(f.size)]

a = IO.read("phrases_no_extra.txt").
  split( /[\r?\n]+/ ).
  reject{|s|
    # Reject if length is less than 2 or if it contains
    # a [ or if it's composed entirely of upper case
    # letters and spaces.
    s.size < 2 or s.index "[" or s =~ /^[A-Z ]+$/ }

puts a[ rand( a.size ) ]

irb(main):004:0> [1, 2].collect do |i| i+3; end.join " : "
=> "4 : 5"

The method call is not on the "end" but on the result of the method
using the block that the "end", well, 'closes'. Very functional.

Best regards,

···

On 9/7/07, Lloyd Linklater <lloyd@2live4.com> wrote:

Jeremy Woertink wrote:
> end.delete_at(-1)

OMG! You can call methods in an end??? I have lived far to long in the
scalar world! When would you do such a thing?

--
John Mettraux -///- http://jmettraux.openwfe.org

Remember do..end is just another way of saying {..}

If I need to filter things out of an array of data I often do things like:

data = [1,2,3,4,5,6,6,7,7]
data.find_all{|x| x > 5}.uniq
=> [6, 7]

Thats just the same as:

data.find_all do |x|
   x > 5
end.uniq
=> [6, 7]

I do tend to use the {..} syntax if I'm chaining calls like this though because 'calling' methods on end looks weird to me as well.

Alex Gutteridge

Bioinformatics Center
Kyoto University

···

On 7 Sep 2007, at 10:55, Lloyd Linklater wrote:

Jeremy Woertink wrote:

end.delete_at(-1)

OMG! You can call methods in an end??? I have lived far to long in the
scalar world! When would you do such a thing?

quoth the Simon Schuster:

eek. I've never written a unit test before. that's all incredibly
murky territory.. not only am I new to ruby, but new to programming in
general. I'll get around to it someday, I think. it just seems scary.

I used to think that too, but finally I got around to trying them, and they
really aren't that difficult at all. You basically just call functions which
compare known, good values against the values your code generates. The
various canned functions allow you to test almost anything your code ought to
be doing. The Pickaxe book has a great introduction that lays it out simply
and succinctly. You owe it to yourself to check it out...[0]

As I discovered, when you start writing libraries or apps of any appreciable
size the tests become almost indispensable. You will know immediately if any
changes you made broke something anywhere in the code.

I have heard of folks who write unit tests directly from their application's
specs before they even start on code for the app itself. Then, it's simply a
matter of making tests pass, and when they all pass, your done! Truthfully,
that's what I find murky and scary :wink:

-d

[0] Sorry, was going to link to it but it seems that the chapter on unit tests
was added in the second ed. Guess you will have to buy it ... it's worth it,
trust me :wink:

···

--
darren kirby :: Part of the problem since 1976 :: http://badcomputer.org
"...the number of UNIX installations has grown to 10, with more expected..."
- Dennis Ritchie and Ken Thompson, June 1972

I wish that I were awake. That regular expression
wasn't very sensible.

a = IO.read("phrases_no_extra.txt").
  split( /(?:\r?\n)+/ ).
  reject{|s|
    # Reject if it contains a [ or if
    # it's composed entirely of upper case
    # letters and spaces.
    s.index "[" or s =~ /^[A-Z ]+$/ }

puts a[ rand( a.size ) ]

···

On Sep 7, 3:34 am, expandaf...@yahoo.com wrote:

expandaf...@yahoo.com wrote:
> On Sep 6, 7:29 pm, "Simon Schuster" <significa...@gmail.com> wrote:
> > I know this could be more idiomatic to ruby.

> > it's basically to turnhttp://www.gutenberg.org/etext/18362intoan
> > array. the "_no_extras" refers to me having snipped the intro and
> > outro of the text outside of ruby. I still have to do something with
> > the "SECTION" fields and the "A", "B", etc. fields. (not to mention
> > some kind of linguistic parsing which would make f[rand(f.size)] + " "
> > f[rand(f.size)] + " " .... link together in a coherent matter, but
> > that's a little beyond me. any direction in this area would be kindly
> > appreciated though! I'm thinking of separating it into different text
> > files maybe. certain sections are almost whole sentences, they're
> > grouped in all kinds of ways that will maybe help with this. no
> > long-term goal, really, just learning ruby and having fun. :slight_smile:

> > anyhow, the sloppy newbie code is as follows:

> > f = File.read("phrases_no_extra.txt")
> > f = f.to_a
> > f = f.each { |x| x.chop! }
> > f.each_with_index { |x,y| # deletes the empty array items
> > if x.size == 0
> > f.delete_at(y)
> > end
> > }
> > f.each_with_index { |x,y| # deleting all but the last (which is
> > spread of two lines)
> > if x.include? "]" # of his comments
> > f.delete_at(y)
> > end
> > }
> > f.each_with_index { |x,y| # yes, this is me unable to recall
> > how to do "or" hahaha.
> > if x.include? "["
> > f.delete_at(y)
> > end
> > }
> > f.delete_at(-1) # random whitespace item at the end from the last quote

> > puts f[rand(f.size)]

> a = IO.read("phrases_no_extra.txt").
> split( /[\r?\n]+/ ).
> reject{|s|
> # Reject if length is less than 2 or if it contains
> # a [ or if it's composed entirely of upper case
> # letters and spaces.
> s.size < 2 or s.index "[" or s =~ /^[A-Z ]+$/ }

> puts a[ rand( a.size ) ]

That contained some redundancy.

a = IO.read("phrases_no_extra.txt").
  split( /[\r?\n]+/ ).
  reject{|s|
    # Reject if it contains a [ or if
    # it's composed entirely of upper case
    # letters and spaces.
    s.index "[" or s =~ /^[A-Z ]+$/ }

puts a[ rand( a.size ) ]

Simon Schuster wrote:

my local copy has some extra (probably important) authorship/proj
gutenberg info at the beginning and end that I've stripped, but other
than that this code works perfectly.

Yes, you could drop the open-uri stuff and just use your
File.read on your local copy, but I needed something to work
from...

> I really like how it's split up by lines per method. thanks a lot!

'welcome. It reflects the way I think about the problem.
Others may think differently. :slight_smile:

also is \[ a literal bracket, or some kind of grouping device that
just happens to be also the boundary-character I'm looking for?

Literal bracket. Otherwise, it defines a range of characters.
E.g., [a-mA-M0-4] matches the first half of all alphanumerics.

Regards,

···

--
Bil Kleb
http://fun3d.larc.nasa.gov