Hash problem

Hi

I have small problem with adding data to hash table

In loop I take some string and get IP address from it like this:

ip =
/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/.match(title)

and now under ip variable I have my IP which I want to put in hash table
and count if the same IP I will find in another step (loop)

I create hash table
test = Hash.new
and put it in table
test[ip] = 1

But I don’t know how to search table to find if the same ip is already
in table and increase counter

Could You tell me how to do this or give me just a clue how to figure
this out ?

2010/3/25 Adam N. [email protected]:

and count if the same IP I will find in another step (loop)
this out ?
The usual idiom for counting is this:

counters = Hash.new 0

counters[ip] += 1

If you want to print sorted descending by count, you can do

counters.sort_by {|ip,cnt| -cnt}.each do |ip,cnt|
printf “%6d %s\n”, cnt, ip
end

Kind regards

robert

On Thu, Mar 25, 2010 at 9:16 AM, Adam N. [email protected] wrote:

and count if the same IP I will find in another step (loop)
this out ?
A typical idiom is this:

irb(main):007:0> h = Hash.new(0)
=> {}
irb(main):008:0> h[“10.1.1.1”] += 1
=> 1
irb(main):009:0> h[“10.1.1.1”] += 1
=> 2
irb(main):010:0> h[“10.1.1.2”] += 1
=> 1
irb(main):011:0> h[“10.1.1.3”] += 1
=> 1
irb(main):012:0> h
=> {“10.1.1.1”=>2, “10.1.1.2”=>1, “10.1.1.3”=>1}

That constructor of Hash receives a default value for a non-existing
key, so when you do this:

h[k] += v

it means

h[k] = h[k] + v

The right hand side h[k] evaluates to the default value if k is not in
the hash, as in your case the first time you add an IP.

Jesus.

On Thu, Mar 25, 2010 at 10:29 AM, Adam N. [email protected]
wrote:

First of all, with the mechanism of the default value you don’t need
to check for the key to set the initial value. It’s done for you, as I
explained before:

h = Hash.new(0)
h[k] += 1

will set h[k] to 1 the first time, and increase it by one afterwards.

On the other hand, this does work for me:

irb(main):020:0> if h.has_key?(“10.1.1.3”) == true
irb(main):021:1> puts “found”
irb(main):022:1> end
found

Although for boolean comparison, the idiomatic way is to check against
the expression itself, instead of comparing to true, since in Ruby
anything that is not nil or false will be “truthy” in a boolean
expression

irb(main):017:0> if h.has_key?(“10.1.1.3”)
irb(main):018:1> puts “found”
irb(main):019:1> end
found

Jesus.

Le 25 mars à 10:29, Adam N. a écrit :

but this doesn’t work :confused:

It should. Show us your whole code, not just snippets - the problem
lies somewhere else.

h = Hash.new(0)
=> {}

if h.has_key?(“1.2.3.4”)
puts “In table.”
else
?> h[“1.2.3.4”] = 1

end
=> 1

if h.has_key?(“1.2.3.4”)
puts “In table.”
else
?> h[“1.2.3.4”] = 1

end
In table.
=> nil

h.has_key?(“1.2.3.4”)
=> true

Fred

Ok - I know how to increase counter - bigger problem is with how to find
this ip in table

This is how I try to do this:

if test.has_key?(ip) == true
print “ip in table”
else
test[ip] = 1
end

but this doesn’t work :confused:

F. Senault wrote:

Le 25 mars � 10:29, Adam N. a �crit :

but this doesn’t work :confused:

It should. Show us your whole code, not just snippets - the problem
lies somewhere else.

h = Hash.new(0)
=> {}

if h.has_key?(“1.2.3.4”)
puts “In table.”
else
?> h[“1.2.3.4”] = 1

end
=> 1

if h.has_key?(“1.2.3.4”)
puts “In table.”
else
?> h[“1.2.3.4”] = 1

end
In table.
=> nil

h.has_key?(“1.2.3.4”)
=> true

Fred

Ok - here is code:

login = ‘aaa’
test = Hash.new

imap = Net::IMAP.new(‘imap-server’,993,true)
puts "passwd: "
pass = gets.chop
imap.login(login,pass)
imap.select(‘example’)
imap.uid_search([“SUBJECT”, “To-check”,
“NOT”, “SEEN”]).each do |uid|
mess = imap.uid_fetch(uid, “ENVELOPE”)[0].attr[“ENVELOPE”]
title = mess.subject
ip =
/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/.match(title)
if test.has_key?(ip)
test[ip] += 1
else
test[ip] = 1
end
end
imap.logout()
imap.disconnect()

I try with else test[ip] = 1 and without else - it still doesn’t work
like I need - maybe there is problem with “” or ‘’ because I don’t set
it when I put key to hash table

Robert K. wrote:

2010/3/25 Adam N. [email protected]:

if h.has_key?(“1.2.3.4”)
In table.

/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/.match(title)
like I need - maybe there is problem with “” or ‘’ because I don’t set
it when I put key to hash table

ip is of type MatchData. What you want is a String.

irb(main):001:0> ip = “foo”.match /o+/
=> #<MatchData “oo”>
irb(main):002:0> ip[0]
=> “oo”

Kind regards

robert

Yes - MatchData - the problem is solved :slight_smile:

Thanks for all

2010/3/25 Adam N. [email protected]:

if h.has_key?(“1.2.3.4”)
In table.

/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/.match(title)
like I need - maybe there is problem with “” or ‘’ because I don’t set
it when I put key to hash table

ip is of type MatchData. What you want is a String.

irb(main):001:0> ip = “foo”.match /o+/
=> #<MatchData “oo”>
irb(main):002:0> ip[0]
=> “oo”

Kind regards

robert

On Mar 25, 2010, at 6:16 AM, Adam N. wrote:

Ok - here is code:

login = ‘aaa’
test = Hash.new

You can still simplify this with the suggestion that you received from
several others. Initialize your hash as:

test = Hash.new(0)

So that missing keys will appear as 0. (see note at end, too)

   ip =

/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4]
[0-9]|[01]?[0-9][0-9]?)/.match(title)
if test.has_key?(ip)
test[ip] += 1
else
test[ip] = 1
end

Then you don’t need to have this if, just put: (including where Robert
pointed out that ip holds a MatchData object.

              test[ip[0]] += 1

Which is syntactic sugar for:
test[ip[0]] = test[ip[0]] + 1

If that key (ip[0]) doesn’t exist, it behaves like
test[ip[0]] = 0 + 1

end
imap.logout()
imap.disconnect()

I try with else test[ip] = 1 and without else - it still doesn’t work
like I need - maybe there is problem with “” or ‘’ because I don’t set
it when I put key to hash table

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

-Rob

*Note: In general, if you want to set up a hash this way, you might
need to specifically assign to the hash like:

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

but a Fixnum is immutable so there’s no problem “sharing” the value
0. If you were adding to an Array, these two initializations would
lead to different results:

test = Hash.new([])
test = Hash.new {|h,k| h[k] = [] }

(What those results are is left as an exercise for the reader :wink:

Rob B. http://agileconsultingllc.com
[email protected]