new to Ruby - pls help in translating this

S

Sam Dela Cruz

--=_alternative 006751FE882570D2_=
Content-Type: text/plain; charset="US-ASCII"

Hi,

I'm starting to use Ruby in one of my projects at work. I'm coming from a
Perl background.
In my project I would need to parse a list of numbers (thousands of them)
and then return the duplicates. In perl, I can do this:

##### Perl code
%hash = {};
while (<>)
{
chomp;
$hash{$_}++;
}

foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n" if ($hash{$key} > 1);
}

I tried to translate this in Ruby, but could not find en equivalent of
$hash{$_}++, this is auto increment.
Can somebody tell me how this is to be done in Ruby? Or maybe the Ruby
way on how to attack this whole thing. Thanks.

Regards,
Sam
--=_alternative 006751FE882570D2_=--
 
J

James Edward Gray II

Hi,

I'm starting to use Ruby in one of my projects at work. I'm coming
from a
Perl background.
In my project I would need to parse a list of numbers (thousands of
them)
and then return the duplicates. In perl, I can do this:

##### Perl code
%hash = {};
while (<>)
{
chomp;
$hash{$_}++;
}

foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n" if ($hash{$key} > 1);
}

I tried to translate this in Ruby, but could not find en equivalent of
$hash{$_}++, this is auto increment.

See if this gets you going:

seen = Hash.new(0)
ARGF.each_line { |line| seen[line.strip] += 1 }

seen.each { |key, value| puts key if value > 1 }

James Edward Gray II
 
D

Dan Diebolt

--0-111865063-1134155277=:55437
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

use the following to initiate your hash:
=20
h=3DHash.new(0)
=20
and this to increment on each key:
=20
h[key] =3D h[key] + 1

=09
 
M

Michael Fellinger

--nextPart2593319.70Ojd7Xiaq
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hey,

after looking at your code (wich was a bit hard, since i don't speak perl) =
=2D i=20
came up with following solution, that doesn't seem very ruby-esque but work=
s=20
well for me.
I'm sure someone brings the code down to one line, but i'm a bit too lazy t=
o=20
try that :)

file =3D File.open(ARGV[0]).readlines
h =3D {}
file.each{|x| (h[x].nil?) ? (h[x] =3D 1) : (h[x] =3D h[x]+=3D1)}
h.each_pair{|k,v| puts "#{k.strip} appears #{v} times" if v >=3D 2}

Am Freitag, 9. Dezember 2005 19:48 schrieb Sam Dela Cruz:
Hi,

I'm starting to use Ruby in one of my projects at work. I'm coming from a
Perl background.
In my project I would need to parse a list of numbers (thousands of them)
and then return the duplicates. In perl, I can do this:

##### Perl code
%hash =3D {};
while (<>)
{
chomp;
$hash{$_}++;
}

foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n" if ($hash{$key} > 1);
}

I tried to translate this in Ruby, but could not find en equivalent of
$hash{$_}++, this is auto increment.
Can somebody tell me how this is to be done in Ruby? Or maybe the Ruby
way on how to attack this whole thing. Thanks.

Regards,
Sam

--nextPart2593319.70Ojd7Xiaq
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDmdd8MdQeL6eBxhIRAjkCAJ9Xl6Gcu+jPkn+KkaksxzLLd8yhywCg0dkd
RpwC7Xt6ZUMuJKk8SEfxaAU=
=xeN0
-----END PGP SIGNATURE-----

--nextPart2593319.70Ojd7Xiaq--
 
L

Logan Capaldo

Hi,

I'm starting to use Ruby in one of my projects at work. I'm coming
from a
Perl background.
In my project I would need to parse a list of numbers (thousands of
them)
and then return the duplicates. In perl, I can do this:

##### Perl code
%hash = {};
while (<>)
{
chomp;
$hash{$_}++;
}

foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n" if ($hash{$key} > 1);
}

hash = Hash.new { |h, k| h[k] = 0 }

while gets
$_.chomp!
hash[$_] += 1
end
I tried to translate this in Ruby, but could not find en equivalent of
$hash{$_}++, this is auto increment.

Ruby has no auto-increment since variables are more like labels on
objects than containers for objects and numbers are generally
immutable in ruby.
IOW:
x = 3
x++ in ruby would be like typing 3++ which doesn't make sense really.
 
P

pat eyler

Hi,

I'm starting to use Ruby in one of my projects at work. I'm coming from = a
Perl background.
In my project I would need to parse a list of numbers (thousands of them)
and then return the duplicates. In perl, I can do this:
[elided perl goo]

I tried to translate this in Ruby, but could not find en equivalent of
$hash{$_}++, this is auto increment.
Can somebody tell me how this is to be done in Ruby?

translating from Perl to Ruby seems often to be a bad idea ... a
common idea, but not necessarily a good one. I'd rather work
with a Ruby solution to a problem than a Rubification of a Perl
solution to a problem.
Or maybe the Ruby
way on how to attack this whole thing. Thanks.

I'm assuming that your list comes from a file (but you can change that
pretty easily in the code below), given that, how about something like:


seen_ary =3D Array.new

File.open("nums","r").each do |elem|
print elem if seen_ary.include?(elem)
seen_ary.push(elem)
end

(there are probably still better ways of doing this though)
 
J

JB Eriksson

------=_Part_10186_18470900.1134156277131
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

well, there is the succ method. and there's a succ! on String, which could
work in this case, I guess(?), since:

irb(main):023:0> a =3D "9"
=3D> "9"
irb(main):024:0> a.succ!
=3D> "10"


Hi,

I'm starting to use Ruby in one of my projects at work. I'm coming
from a
Perl background.
In my project I would need to parse a list of numbers (thousands of
them)
and then return the duplicates. In perl, I can do this:

##### Perl code
%hash =3D {};
while (<>)
{
chomp;
$hash{$_}++;
}

foreach my $key (sort keys %hash)
{
print "$key: $hash{$key}\n" if ($hash{$key} > 1);
}

hash =3D Hash.new { |h, k| h[k] =3D 0 }

while gets
$_.chomp!
hash[$_] +=3D 1
end
I tried to translate this in Ruby, but could not find en equivalent of
$hash{$_}++, this is auto increment.

Ruby has no auto-increment since variables are more like labels on
objects than containers for objects and numbers are generally
immutable in ruby.
IOW:
x =3D 3
x++ in ruby would be like typing 3++ which doesn't make sense really.
Can somebody tell me how this is to be done in Ruby? Or maybe the
Ruby
way on how to attack this whole thing. Thanks.

Regards,
Sam

------=_Part_10186_18470900.1134156277131--
 
D

Dan Diebolt

--0-462817583-1134156660=:31051
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable
variables are more like labels on objects than containers for objects=20
=20
There is something very fundamental about what you are saying here but =
I don't quite understand. Could you elaborate on this with perhaps an exa=
mple?

=09
 
W

Wilson Bilkovich

Or, something else to think about.. shamelessly borrowed from this
mailing list a month or so ago..
Wrapped in lame 'gets' code to let you play with it at the command
line. I presume you'd actually do something cooler with STDIN or a
filename.

class Array
def dups
h, d =3D {}, []; each{|e| h[e] ? (d << h.delete(e)) : (h[e] =3D e)}; d
end
end
numbers =3D []
while n =3D STDIN.gets.chomp
break if n =3D=3D ''
numbers << n
end
puts numbers.dups

I love reopening Array.

--Wilson.
 
E

Eric Hodel

Hi,

I'm starting to use Ruby in one of my projects at work. I'm
coming from a
Perl background.
In my project I would need to parse a list of numbers (thousands
of them)
and then return the duplicates. In perl, I can do this:
[elided perl goo]

I tried to translate this in Ruby, but could not find en
equivalent of
$hash{$_}++, this is auto increment.
Can somebody tell me how this is to be done in Ruby?

translating from Perl to Ruby seems often to be a bad idea ... a
common idea, but not necessarily a good one. I'd rather work
with a Ruby solution to a problem than a Rubification of a Perl
solution to a problem.

Ditto. I often find that I can make my code close to readable
English and find that a very good thing.
I'm assuming that your list comes from a file (but you can change that
pretty easily in the code below), given that, how about something
like:

seen_ary = Array.new

File.open("nums","r").each do |elem|
print elem if seen_ary.include?(elem)
seen_ary.push(elem)
end

(there are probably still better ways of doing this though)

I'll go with:

seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end
 
S

Simon Kröger

I'll go with:

seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

Thanks, this is how ruby should look like!

here is another one (i like it a bit more
functional style):

quantities = Hash.new{|h, k| h[k]=0}
ARGF.each{|l| quantities[l.chomp.to_i] += 1}
puts quantities.delete_if{|k, v| v <= 1}.keys

cheers

Simon
 
E

Eric Hodel

Or, something else to think about.. shamelessly borrowed from this
mailing list a month or so ago..
Wrapped in lame 'gets' code to let you play with it at the command
line. I presume you'd actually do something cooler with STDIN or a
filename.

class Array
def dups
h, d = {}, []; each{|e| h[e] ? (d << h.delete(e)) : (h[e] =
e)}; d
end
end

That is far too complicated and impossible to read. I think we
should be giving new people examples of how to make code clear and
expressive.
numbers = []
while n = STDIN.gets.chomp

$ echo -n '' | ruby -e 'p STDIN.gets'
nil
break if n == ''
numbers << n
end
puts numbers.dups

I love reopening Array.

I like clear, expressive code: [ruby-talk:169927]
 
D

dblack

--8323328-218870398-1134159926=:15796
Content-Type: MULTIPART/MIXED; BOUNDARY="8323328-218870398-1134159926=:15796"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-218870398-1134159926=:15796
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

I'll go with:
=20
seen =3D {}
=20
ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] =3D true
end

Thanks, this is how ruby should look like!

here is another one (i like it a bit more
functional style):

quantities =3D Hash.new{|h, k| h[k]=3D0}
ARGF.each{|l| quantities[l.chomp.to_i] +=3D 1}

Since you're doing a h[x] +=3D 1 thing, you don't need to do the
auto-assignment in the block:

quantities =3D Hash.new(0)

will work fine.

Also, String#to_i is smart enough not to need the chomp.

So, as so often happens, code evaporates from the screen as one works
on a Ruby program :)


David

--=20
David A. Black
(e-mail address removed)

"Ruby for Rails", forthcoming from Manning Publications, April 2006!
--8323328-218870398-1134159926=:15796--
--8323328-218870398-1134159926=:15796--
 
L

Logan Capaldo

There is something very fundamental about what you are saying
here but I don't quite understand. Could you elaborate on this with
perhaps an example?

Well basically, all variables in ruby are references (or pointers,
whatever you want to call them), but they are actually even less
"clingy" than that.

maybe an example will help

x = "a string"
y = x # this doesn't do something like x.copy nor is it even
equalivalent to typing y = "a string"
# it more like saying
# x =
# "a string"
# y =

y.upcase! #=> "A STRING"
x #=> "A STRING"

Just think of varibles as a way to refer to a memory address
If x and y "contain" anythjing it is a memory address and they both
have the same memory.

Basically they are pointers. Except when they aren't. Fixnums for
instance are stored as values. As are symbols. I think I might have
over complicated this. Maybe someone else can explain it better.
 
L

Logan Capaldo

--Apple-Mail-4--913240869
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed


well, there is the succ method. and there's a succ! on String,
which could
work in this case, I guess(?), since:

irb(main):023:0> a = "9"
=> "9"
irb(main):024:0> a.succ!
=> "10"

Well, if it was a string. The problem is fixnums are immediate
values. ++ would therefore be an operation on the variable a, rather
than the object that a points at.
--Apple-Mail-4--913240869--
 
S

Sam Dela Cruz

--=_alternative 0072BA1F882570D2_=
Content-Type: text/plain; charset="US-ASCII"

Thank you all. I learned a little bit more ruby. And yes, I want to do
things the Ruby way, but I just can't help to think perl still and then
translate to ruby. This is very similar to when I came to the U.S. and
all of a sudden I have to talk in English, I still think in my original
language(Tagalog) and then translate it in English and it doesn't always
come up the way English speakers would say it. But I get the point
accross. But yes, going back to Ruby, I'd like to learn things the Ruby
way and so far I have good things to say about Ruby. One, it being so
readable, and second I think it is easier to learn especially the OOP part
of it. In perl OOP is a big hurdle.

Here's what I decided on using (looks more like what I originally posted
in perl):

hash = Hash.new(0)
File.open(ARGV[0],"r").each do |line|
hash[line.chomp] += 1
end

hash.keys.sort.each do |key|
puts "#{key}: #{hash[key]}" if hash[key] > 1
end

Regards,
Sam Dela Cruz









Eric Hodel <[email protected]>
12/09/2005 11:39 AM
Please respond to
(e-mail address removed)


To
(e-mail address removed) (ruby-talk ML)
cc

Subject
Re: new to Ruby - pls help in translating this
Classification







Hi,

I'm starting to use Ruby in one of my projects at work. I'm
coming from a
Perl background.
In my project I would need to parse a list of numbers (thousands
of them)
and then return the duplicates. In perl, I can do this:
[elided perl goo]

I tried to translate this in Ruby, but could not find en
equivalent of
$hash{$_}++, this is auto increment.
Can somebody tell me how this is to be done in Ruby?

translating from Perl to Ruby seems often to be a bad idea ... a
common idea, but not necessarily a good one. I'd rather work
with a Ruby solution to a problem than a Rubification of a Perl
solution to a problem.

Ditto. I often find that I can make my code close to readable
English and find that a very good thing.
I'm assuming that your list comes from a file (but you can change that
pretty easily in the code below), given that, how about something
like:

seen_ary = Array.new

File.open("nums","r").each do |elem|
print elem if seen_ary.include?(elem)
seen_ary.push(elem)
end

(there are probably still better ways of doing this though)

I'll go with:

seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

--
Eric Hodel - (e-mail address removed) - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com





--=_alternative 0072BA1F882570D2_=--
 
J

James Edward Gray II

Here's what I decided on using (looks more like what I originally
posted
in perl):

hash = Hash.new(0)
File.open(ARGV[0],"r").each do |line|

Replacing the above with:

ARGF.each do |line|

Is the same thing, but more powerful. You could feed it multiple
files at once, or use it in pipelined processing. Just FYI.

James Edward Gray II
hash[line.chomp] += 1
end

hash.keys.sort.each do |key|
puts "#{key}: #{hash[key]}" if hash[key] > 1
end

Regards,
Sam Dela Cruz









Eric Hodel <[email protected]>
12/09/2005 11:39 AM
Please respond to
(e-mail address removed)


To
(e-mail address removed) (ruby-talk ML)
cc

Subject
Re: new to Ruby - pls help in translating this
Classification







Hi,

I'm starting to use Ruby in one of my projects at work. I'm
coming from a
Perl background.
In my project I would need to parse a list of numbers (thousands
of them)
and then return the duplicates. In perl, I can do this:
[elided perl goo]

I tried to translate this in Ruby, but could not find en
equivalent of
$hash{$_}++, this is auto increment.
Can somebody tell me how this is to be done in Ruby?

translating from Perl to Ruby seems often to be a bad idea ... a
common idea, but not necessarily a good one. I'd rather work
with a Ruby solution to a problem than a Rubification of a Perl
solution to a problem.

Ditto. I often find that I can make my code close to readable
English and find that a very good thing.
I'm assuming that your list comes from a file (but you can change
that
pretty easily in the code below), given that, how about something
like:

seen_ary = Array.new

File.open("nums","r").each do |elem|
print elem if seen_ary.include?(elem)
seen_ary.push(elem)
end

(there are probably still better ways of doing this though)

I'll go with:

seen = {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] = true
end

--
Eric Hodel - (e-mail address removed) - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
 
M

Michael Fellinger

--nextPart1863028.yCRFmJ0X3y
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Am Freitag, 9. Dezember 2005 21:31 schrieb Logan Capaldo:
Well, if it was a string. The problem is fixnums are immediate
values. ++ would therefore be an operation on the variable a, rather
than the object that a points at.

well, there is a+=1
and a++ would be a+! imho...

--nextPart1863028.yCRFmJ0X3y
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBDmfTZMdQeL6eBxhIRAvNfAJ9YvmCs4OIvdvuyE8e1ys8+aYmB+wCguD1J
TkP04eXhdBlkZs1Cg42dN1Q=
=7lb8
-----END PGP SIGNATURE-----

--nextPart1863028.yCRFmJ0X3y--
 
S

Simon Kröger

quantities = Hash.new{|h, k| h[k]=0}
ARGF.each{|l| quantities[l.chomp.to_i] += 1}


Since you're doing a h[x] += 1 thing, you don't need to do the
auto-assignment in the block:

quantities = Hash.new(0)

will work fine.

yes, saw that after pressing the submit button, but as said before
using this form of Hash.new is source of hard to track bugs.
Also, String#to_i is smart enough not to need the chomp.

So, as so often happens, code evaporates from the screen as one works
on a Ruby program :)

you are so true:

require 'set'
seen = Set.new
puts ARGF.reject{|l| seen.add? l}


cheers

Simon
 
P

pat eyler

seen_ary =3D Array.new

File.open("nums","r").each do |elem|
print elem if seen_ary.include?(elem)
seen_ary.push(elem)
end

(there are probably still better ways of doing this though)

I'll go with:

seen =3D {}

ARGF.each do |elem|
print elem if seen.include? elem
seen[elem] =3D true
end

And yes, this way is much better (I knew it would be but, it's nice to
see just how much better):


require 'benchmark'
n =3D 100

# build a big array with lots of duplication
@nums =3D (1..1_000).to_a
(1..1_000).step(17) {|num| @nums.push(num) }


# set up two versions of our rubylike version
# the original perl-like version and the
# final version
def as_ary
seen_ary =3D Array.new

@nums.each do |elem|
$stderr.print elem if seen_ary.include?(elem)
seen_ary.push(elem)
end
end

def as_hash
seen =3D Hash.new

@nums.each do |elem|
$stderr.print elem if seen.include?(elem)
seen[elem] =3D true
end
end

# then benchmark them to see how they perform
Benchmark.bm(10) do |x|
x.report("as Array") {for i in 1..n; as_ary; end }
x.report("as Hash") {for i in 1..n; as_hash; end }
end

# and the results are:
# ./print_dups.rb 2> /dev/null
# user system total real
#as Array 12.690000 0.030000 12.720000 ( 13.940651)
#as Hash 0.230000 0.000000 0.230000 ( 0.613217)
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top