what's the Ruby way to do this?

M

Miles Keaton

What's the Ruby way to do this?
If I want to get the first 10 words from a phrase, followed by "..."?
Although the following works, I can tell it's just not Rubyish:

def snippet(thought)
result = ''
i = 0
thought.split.each do |word|
if i < 10
result = (result + ' ' + word)
end
i = (i + 1)
end
result = result.strip + '...'
return result
end
 
E

Erik Veenstra

What's the Ruby way to do this?
If I want to get the first 10 words from a phrase, followed by "..."?
Although the following works, I can tell it's just not Rubyish:

def snippet(thought)
result = ''
i = 0
thought.split.each do |word|
if i < 10
result = (result + ' ' + word)
end
i = (i + 1)
end
result = result.strip + '...'
return result
end

def snippet(thought)
thought.split[0..9].join(" ") + "..."
end

gegroet,
Erik V.
 
F

Florian Gross

Miles said:
What's the Ruby way to do this?
If I want to get the first 10 words from a phrase, followed by "..."?

def snippet(thought)
words = thought.split
result = words.first(10).join(" ")
result += "..." if words.size > 10
return result
end
 
W

William James

def snippet(thought)
thought.match(/([^\s]+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end

puts snippet("The quick red fox jumps over the lazy brown fat hog.")
puts snippet("The quick red fox jumps over the lazy brown hog.")
puts snippet("The quick red fox jumps over the lazy brown")

The quick red fox jumps over the lazy brown fat ...
The quick red fox jumps over the lazy brown hog.
The quick red fox jumps over the lazy brown
 
B

Belorion

def snippet(thought)
thought.match(/([^\s]+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end

That is most certainly a precise and accurate solution, but to me the
"Ruby Way" is short, conscise code which is *readable*

In which case I would suppor the notion that
def snippet(thought)
thought.split[0..9].join(" ") + "..."
end

is more the "Ruby Way"
 
W

William James

georgesawyer said:
match(/([^\s]+(\s+|$)){0,10}/)[0]+($'>""?"...":"")

This is a good way, seriously, for a Perl programmer moving to Ruby to
maintain job security.

I don't know Perl. However, any programmer worth his salt
knows regular expressions. I think you would be well rewarded
if you looked into them.
Ruby is using the tactic, "embrace and extend."

Then why haven't you embraced regular expressions and the
"Perl way"?


Belorion wrote
def snippet(thought)
thought.match(/([^\s]+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end


That is most certainly a precise and accurate solution, but to me the
"Ruby Way" is short, conscise code which is *readable*

In which case I would suppor the notion that
def snippet(thought)
thought.split[0..9].join(" ") + "..."
end


The programmers among you will have seen that my solution wasn't
designed to be equivalent to the above code; instead it emulates
Gross's solution:

def snippet(thought)
words = thought.split
result = words.first(10).join(" ")
result += "..." if words.size > 10
return result
end

"..." is appended *only* if there are remaining words.


Douglas Livingstone wrote
def snippet(thought)
thought.split[0..9].join(" ") + "..."
end
is more the "Ruby Way"

Shorter too.

Egad! Another one!


Belorion wrote
is more the "Ruby Way"

I didn't realize that you are the arbiter of what is proper
use of Ruby. Glad to meet you, Belorian.

A fellow that doesn't have your high authority wrote something
with which I concur:

"The common term for patterns that use this strange vocabulary
is regular expressions. In ruby, as in Perl, they are generally
surrounded by forward slashes rather than double quotes. If you
have never worked with regular expressions before, they
probably look anything but regular, but you would be wise
to spend some time getting familiar with them. They have an
efficient expressive power that will save you headaches (and
many lines of code) whenever you need to do pattern matching,
searching, or other manipulations on text strings."

Admittedly, his words don't carry as much weight as yours,
but I think they make a lot of sense. Note where he says that
regular expressions can replace "many lines of code", a practice
of which he seems to approve. Please forgive him, if not me,
Belorian.

"If you have never worked with regular expressions before,
they probably look anything but regular".

How true that is! I am not as familiar with Ruby-style
regular expressions as I would like to be, since I've done
much more programming in Awk, which has less powerful ones.
I see now that I could have made it shorter (and I wouldn't
be surprised if Florian Gross could make it "yet shorter"):

def snippet(thought)
thought.match(/(\S+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end

It's really quite straightforward. Broken down:

thought.match(
/ Begin reg.exp.
( Begin group.
\S+ Match non-whitespace sequence.
(\s+|$) Match whitespace or end of string.
) End group.
{0,10} Match group up to 10 times (grab 10 words).
/ End reg.exp.
)[0] The matched portion of string.
+ Concatenate 2 strings.
($'>"" If the rest of the string following the match isn't empty...
?"...":"") ... tack on "..."; else tack on empty string.
 
B

Belorion

In which case I would support the notion that
def snippet(thought)
thought.split[0..9].join(" ") + "..."
end
is more the "Ruby Way"
I didn't realize that you are the arbiter of what is proper
use of Ruby. Glad to meet you, Belorian.

If you take the sentence in full context, you will see that I am
making no such claim.

The full sentence read "In which case I would support the notion that
[...] is more the 'Ruby Way'"

"support the notion" is hardly proclaming myself the arbiter of what is proper.
 
B

Belorion

Sorry to post again so soon after my last post -- my reply box lost
focus and enter sent the message instead of a newline...

Anyway...

Admittedly, his words don't carry as much weight as yours,
but I think they make a lot of sense. Note where he says that
regular expressions can replace "many lines of code", a practice
of which he seems to approve. Please forgive him, if not me,
Belorian.

"If you have never worked with regular expressions before,
they probably look anything but regular".

How true that is! I am not as familiar with Ruby-style
regular expressions as I would like to be, since I've done
much more programming in Awk, which has less powerful ones.
I see now that I could have made it shorter (and I wouldn't
be surprised if Florian Gross could make it "yet shorter"):

def snippet(thought)
thought.match(/(\S+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end

I did not mean to imply regular expressions are in poor form. They
are quite powerful, and I think Ruby would be crippled without them.
Rather, I was of the opinion that the other solutions were more
approriate for the simplicity of the problem, and that *always* using
regular expressions can complicate matters that don't need
complicating. One of the things I love about Ruby the most is the
simplicity of the solutions you can come up with.
 
G

Gennady Bystritksy

Douglas said:
def snippet(thought)
thought.split[0..9].join(" ") + "..."
end

is more the "Ruby Way"


Shorter too.

Works differently, though ;-) -- it adds "..." to any result, while the
regexp version adds "..." only if a phrase has been truncated. To make
it equivalent non-regexp one without using termporary storage, I could
come up with the following:

def snippet(thought, n = 10)
[ thought.split[0, n+1] ].map { |a|
a[0, n] + (a[n] && '...').to_a
}.join(' ')
end

Gennady.
 
M

Mark Hubbart

<snip scathing sarcasm> Glad to meet you, Belorian.

owch. Did that raise you up a notch?
def snippet(thought)
thought.match(/(\S+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end

It's really quite straightforward. Broken down:

Though I feel I am at least somewhat experienced in the regexp way, I
still balked a little when I saw that... yes, I could read it, but it
was not nearly as easy to read as the ruby code. There was altogether
too much punctuation on that line for my taste :) Still, using a
regexp has the desirable attribute of being non-lossy, while the
split-join method does not. Here's a slightly simplified example that
makes use of #sub to do the dirty work:

def snippet(thought)
thought.sub(/((?:\S+\s+){10}).+/) {$1 + "..."}
end

t = "It is better to have loved and lost, than never to have loved at
all." # size: 15 words
u = "To be or not to be, that is the question." # size: 10 words

snippet t
==>"It is better to have loved and lost, than never ..."
snippet u
==>"To be or not to be, that is the question."

In this one, #sub tries to replace the expression, but it fails if
there are less than ten words, returning the unmodified string.
Otherwise, the first ten words are captured, then appended with
ellipses. The ellipses are not added on the second quote, since it
just squeaks in under the ten word limit. (This could be modified to
eliminate the trailing space, but I didn't want to bother with that
just now :)


A #split solution that behaves similarly, but not exactly:

def snippet(thought)
thought.split[0..9].join(" ") +
(thought.split.size > 10 ? "..." : "")
end

cheers,
Mark
 
F

Florian Gross

William said:
"If you have never worked with regular expressions before,
they probably look anything but regular".

How true that is! I am not as familiar with Ruby-style
regular expressions as I would like to be, since I've done
much more programming in Awk, which has less powerful ones.
I see now that I could have made it shorter (and I wouldn't
be surprised if Florian Gross could make it "yet shorter"):

def snippet(thought)
thought.match(/(\S+(\s+|$)){0,10}/)[0]+($'>""?"...":"")
end

Let's try then:

def snippet(thought)
result = thought.clone
result[/^(?:\S*\s+){9}\S*(.+)$/, 1] = "..."
ensure
return result
end

def snippet(thought)
thought.sub(/^((?:\S*\s+){9}\S*)(.+)$/, '\1...')
end

But actually I still prefer the solution I gave earlier. Regexps are
harder to understand than the equivalent code and gain you little in
this case. (Even if you know them, there's still some advanced trickery
involved in our pieces of code.)
 

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

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top