help me condence my code?

S

Simon Schuster

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. :)

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)]
 
J

Jeremy Woertink

Simon said:
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. :)

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
 
P

Phlip

Simon said:
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.
 
L

Lloyd Linklater

Jeremy said:
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?
 
J

John Mettraux

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?

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,
 
A

Alex Gutteridge

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?

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
 
S

Simon Schuster

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?
 
S

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.
:)
 
S

Simon Schuster

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?


Simon said:
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,
 
A

Alex Gutteridge

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)]

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
 
R

rio4ruby

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. :)

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
 
D

darren kirby

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 ;)

-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 ;)
 
P

Pete Yandell

Ok, I'm going to try break this down a bit more than the other answers.
Simon said:
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. :)

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
http://notahat.com/
 
E

expandafter

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. :)

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 ) ]
 
E

expandafter

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. :)

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 ) ]
 
E

expandafter

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. :)
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 ) ]

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 ) ]
 
B

Bil Kleb

Simon said:
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. :)
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,
 
L

Lloyd Linklater

John said:
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?

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.

That is just too cool for words. Thanks for getting back to me!
 
W

William James

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. :)

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) ] }
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,264
Messages
2,571,323
Members
48,006
Latest member
MelinaLema

Latest Threads

Top