I’m not even sure if the enumerable method ‘any’ is used
correctly.
No, it’s not how it’s intended to be used.
The idea behind ‘any?’ is to return true if the block returns true for
any of the elements. So the block is expected to return a “truthy”
value.
puts [1,3,7,4].any? { |x| x > 10 } # false
puts [1,3,7,4].any? { |x| x > 5 } # true
However, because your block ends with a “p” statement, which always
returns nil, this will be treated as false always.
So in this case, ‘any?’ is really behaving just as ‘each’, just
iterating over every single element. Also, you’re ignoring the return
value from ‘any?’
Any hints or ideas on how to adjust/improve this piece of code are
welcomed!
Why are you not just taking ‘sorted.first’ as the most frequently found
element?
If you are concerned about getting all the equal top values, then I’d do
something like this:
puts [1,3,7,4].any? { |x| x > 10 } # false
puts [1,3,7,4].any? { |x| x > 5 } # true
However, because your block ends with a “p” statement, which always
returns nil, this will be treated as false always.
So in this case, ‘any?’ is really behaving just as ‘each’, just
iterating over every single element. Also, you’re ignoring the return
value from ‘any?’
Thanks for the detailed explanation. I need to get much more accustomed
to the enumerable and other elementary ruby methods apparently :-/
return sorted.select { |data,no| no == best_count }
The reason is that I didn’t thought about it! All solutions that came to
mind involved several lines of code and functions which made the entire
process feel utterly complicated and wrong for such an easy task. I was
sure that there was an easy - 1 or 2 lines of code - to do this.
Your solution works like a charm! Thanks for the code snippet!
So the ip is referred in the source code as “[entry.split(’ ')[3]]” …
which returns the 4th parameter (if you start counting by 1 the 3rd if
you count in ruby way).
I want to create a list, which contains the IP address (or addresses) of the
most frequently found IP(s).
What does @data_table look like???
What should your method do and what does not work?
@data_table is an Array class, containing multiple strings as the one
above.
(Why do you need the ‘any’ part,
isn’t ‘sorted’ already the list you are looking for?)
There are some “duplicate IP’s” which I want to enumerate. There are two
IP’s that appear 7 times. I want o add these into a secondary list in
order to display them later on in another function.
However, because your block ends with a “p” statement, which always
returns nil, this will be treated as false always.
That statement is true only for 1.8.. Brian, your quarrel with
encoding in 1.9. prevents you from giving correct answers nowadays
when most people seem to use 1.9.* versions:
$ irb19
Ruby version 1.9.3
irb(main):001:0> p 123
123
=> 123
So the ip is referred in the source code as “[entry.split(’ ')[3]]” … which
returns the 4th parameter (if you start counting by 1 the 3rd if you count in ruby
way).
split will break if there can be whitespace between [] (where you have
“ssh-iptables”). I’d rather match IP addresses.
There are some “duplicate IP’s” which I want to enumerate. There are two IP’s
that appear 7 times. I want o add these into a secondary list in order to display
them later on in another function.
Here’s an alternative solution - a tad more involved.
def top_ips
count = Hash.new 0
max = 0
@data_table.each do |line|
ip = line[/\d{1,3}(?:.\d{1,3}){3}/] and max=[max, count[ip] +=
1].max
end
count.select {|ip, c| c == max}.map {|ip, c| ip}
end
OR
def top_ips
count = Hash.new 0
max = 0
@data_table.each do |line|
ip = line[/\d{1,3}(?:.\d{1,3}){3}/] and (count[ip] += 1).tap {|c|
max = c if c > max}
end
count.select {|ip, c| c == max}.map {|ip, c| ip}
end
The idea is to match IP adresses properly, calculate the max along the
way and finally select only those pairs where count == max.
Kind regards
robert
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.