learning the "Ruby way"

M

Mark Wirdnam

**Hobby-programmer alarm**

Hello!
I am trying to learn Ruby, but with the goal of understanding new
elegant solutions, not to repeat the same messy solutions I usually
come up with.
Here is an example I would like to use to improve my understanding.
Any pointers would be great.

Problem:
I have a sorted list ('alfred', 'boris', 'bruce', 'claire', 'dean', 'donald')
and would like to generate or return ('-a-', 'alfred', '-b-', 'boris',
'bruce', '-c-', 'claire', '-d-', 'dean', 'donald').

Here's my solution:
lst = ['alfred', 'boris', 'bruce', 'claire', 'dean', 'donald']
prev = ''
newlst = Array.new
lst.each { |cur|
if cur[0..0] != prev
newlst.push("-#{cur[0..0]}-")
end
newlst.push(cur)
prev = cur[0..0] }

Is this the "Ruby way" of solving this problem? I doubt it, defining
"helper variables" like this is what had to be done in Basic, and my
solution doesn't demonstrate the high degree of readability Ruby is often
praised for.

Any useful suggestions for me? I'd be very grateful!
Mark
 
D

Dan Doel

I'm sure there are many ways of doing this, but here's one:

lst = ['alfred', 'boris', 'bruce', 'claire', 'dean', 'donald']

frob = lst.map do |val|
["-#{val[0..0]}-", val]
end.flatten.uniq

p frob

I'm not sure if #uniq is defined to leave the first occurrence and
delete all the rest or not,
but that's what it currently does, so it works.

- Dan
 
R

Robert Klemme

Dan Doel said:
I'm sure there are many ways of doing this, but here's one:

lst = ['alfred', 'boris', 'bruce', 'claire', 'dean', 'donald']

frob = lst.map do |val|
["-#{val[0..0]}-", val]
end.flatten.uniq

p frob

I'm not sure if #uniq is defined to leave the first occurrence and
delete all the rest or not,
but that's what it currently does, so it works.

There must be an inject way of doing this...

lst = ['alfred', 'boris', 'bruce', 'claire', 'dean', 'donald']

frob = lst.inject( [[], nil] ) do |(res, key), word|
k = "-#{word[0].chr}-"
res << k unless k == key
res << word
[res, k]
end[0]


But this really cries for a Hash, because we have a typical key value
relationship here:

lst = ['alfred', 'boris', 'bruce', 'claire', 'dean', 'donald']

lst.inject( Hash.new {|h,k| h[k]=[]} ) {|res,w| res["-#{w[0].chr}-"] << w;
res}.sort.flatten

In fact, I'd just return the Hash. Then you have the appropriate data
structur. Simply omit ".sort.flatten" from the line above.

Regards

robert
 
G

Gavin Sinclair

Problem:
I have a sorted list ('alfred', 'boris', 'bruce', 'claire', 'dean', 'donald')
and would like to generate or return ('-a-', 'alfred', '-b-', 'boris',
'bruce', '-c-', 'claire', '-d-', 'dean', 'donald').
Here's my solution:
[...]
Is this the "Ruby way" of solving this problem? I doubt it, defining
"helper variables" like this is what had to be done in Basic, and my
solution doesn't demonstrate the high degree of readability Ruby is often
praised for.
Any useful suggestions for me? I'd be very grateful!
Mark


My first thought was to collect the values into a hash

{ 'a' => ['alfred'],
'd' => ['dean', 'donald'],
... }

then render that hash into the array that you want.

It's unlikely to be all that efficient, but both steps are very easy.

Cheers,
Gavin
 
M

Martin DeMello

Mark Wirdnam said:
Problem:
I have a sorted list ('alfred', 'boris', 'bruce', 'claire', 'dean', 'donald')
and would like to generate or return ('-a-', 'alfred', '-b-', 'boris',
'bruce', '-c-', 'claire', '-d-', 'dean', 'donald').

One more way to do it...

require 'enum/cluster' # http://redshift.sourceforge.net/enum

lst = ['alfred', 'boris', 'bruce', 'claire', 'dean', 'donald']

a = ["--#{lst[0][0..0]}--"]
lst.each_cluster(2) {|i, j|
a << i
a << "--#{j[0..0]}--" if i[0] != j[0]
}

p a

martin
 
S

Simon Strandgaard

Is this the "Ruby way" of solving this problem? I doubt it, defining
"helper variables" like this is what had to be done in Basic, and my
solution doesn't demonstrate the high degree of readability Ruby is often
praised for.

Any useful suggestions for me? I'd be very grateful!
Mark

How about this dirty solution ?


server> ruby a.rb
["-a-", "alfred", "-b-", "boris", "bruce", "-c-", "claire", "-d-", "dean", "donald"]
server> expand a.rb
names = %w(alfred boris bruce claire dean donald)
letters = names.map{|name| n=name[0..0]; [n, "-#{n}-"]}.uniq
p (letters + names.zip(names)).sort.transpose[1]
server>
 
M

Mark Wirdnam

ok, I'm not quite there yet, but your helpful examples have given me
an idea how to go about things in Ruby. I think I see a main theme
being to use the power of the pre-defined methods of the
array/string/whatever.
Thanks for your help!

Mark
 

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
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top