How Does Count Method Works in Ruby

How does count method works in Ruby?

Just imagine the "pattern" strings as wrapped by [ and ] from regex syntax, that are matched against each character.

So, if we break a = "hello world" into characters:

[1] pry(main)> a = "hello world"
=> "hello world"
[2] pry(main)> a.split('')
=> ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]

And convert "ej-m" to regex wrapped with [ and ] we get /[ej-m]/ - which means either 'e' or any character from 'j' to 'm'(including both):

[3] pry(main)> a.split('').select{|c| c=~ /[ej-m]/}
=> ["e", "l", "l", "l"]

We got 4 matches - which is also the result you get. Essensially a.count "ej-m" is equivalent to:

[4] pry(main)> a.split('').count{|c| c=~ /[ej-m]/}
=> 4

Multiple arguments to the method are just and between the matches:

[5] pry(main)> a.split('').count{|c| c =~ /[hello]/ and c =~ /[^l]/}
=> 4

How does count work in Ruby

According the documentation, count(p1) for Array

Returns the number of elements. If an argument is given, counts the number of elements which equals to obj. If a block is given, counts the number of elements yielding a true value.

In your case, sentence.downcase.split gives you ["to", "be", "or", "not", "to", "be"]. Here, you have two array elements equaling "to", that's why you obtain 2.

From the documentation of String, count(*args)

Each other_str parameter defines a set of characters to count. The intersection of these sets defines the characters to count in str. Any other_str that starts with a caret (^) is negated. The sequence c1–c2 means all characters between c1 and c2.

If we put aside the negation case, given a String parameter p, call count on a String x returns the number of characters in x matching one of the characters of p.

In your case, you have "llool" in "hello world" matching "lo", i.e. 5

The string count() method

"hello world".count("lo") returns five. It has matched the third, fourth, fifth, eighth, and tenth characters. Lets call this set one.

"hello world".count("o") returns two. It has matched the fifth and eighth characters. Lets call this set two.

"hello world".count("lo", "o") counts the intersection of sets one and two.

The intersection is a third set containing all of the elements of set two that are also in set one. In our example, both sets one and two contain the fifth and eighth characters from the string. That's two characters total. So, count returns two.

How do I recreate Enumerable's count method?

Don't use a default argument. Use *args to collect all the arguments into an array.

def my_count(*args, &block)

if args.length == 1 && !block_given?
# use args[0]
elsif args.length == 1 && block_given?
# use block
elsif args.length == 0 && !block_given?
# no argument/block
else
# raise error
end
end

calling the method 'count' returns wrong number of arguments

I think this is what you were trying to do

def timed_reading(max_length, text)
text.split.delete_if { |y| y.length >= max_length }.count
end

You could just count words with length less than the max anyway

text.split.count { |y| y.length < max_length }

Count initializations of Ruby Class

Instance variables belong to objects (aka instances), that's why they are called instance variables after all. Your first @bar is an instance variable of Foo, your second @bar is an instance variable of the newly-created instance of Foo. Those are two completely different objects (they aren't even of the same class: the newly-created instance is of class Foo, whereas Foo is of class Class).

You obviously need to increment @bar in a method called on Foo, not in a method called on instances of Foo. So, can we think about a method that is a) called on Foo and b) called everytime an instance is created? What about new?

class Foo
@bar = 0

def self.new(*)
@bar += 1
super
end
end

Okay, technically speaking, this doesn't count the number of instances, only the number of times new was called. Sometimes, instances get created without calling new, e.g. when de-serializing. This should be the closest you can get without resorting to ugly hacks of the interpreter internals.

You might think you can override allocate instead (I thought so, too), but I just tested it and it doesn't work. Presumably, the default implementation of new doesn't call allocate via normal means but actually uses the interpreter internal implementation directly.

How to count instances of class without counting reassignment?

In the real world you wouldn't be counting instances in memory, you'd be asking a database how many exist. You need to think in terms of a database.

Your use of a to repeatedly contain the Ticket instance is wrong. You should be using an Array, Hash or Set to maintain the list, then ask the container how many exist:

require 'set'

class Ticket
attr_accessor :price
attr_reader :event, :venue

@@tickets = Set.new

def initialize(event, venue)
@event = event
@venue = venue

@@tickets << self
end

def delete
@@tickets.delete(self)
end

def self.count
@@tickets.size
end

end

a = Ticket.new("Michael Buble", "Staples")
b = Ticket.new("Frank Sinatra", "Madison Square Garden")

puts "Ticket count of #{Ticket::count}"
b.delete
puts "Ticket count of #{Ticket::count}"

You can build this out by adding ways to retrieve a particular instance from @@tickets, add a to_s so you can list them, but, in the end, you'll want to use a real database. If your code were to crash for any reason, your entire list of tickets would disappear, which would be unacceptable in real life.



Related Topics



Leave a reply



Submit