Python has the Counter class in the collections
module. It is a class for counting hashable objects. E.g.:
cnt = Counter()
cnt['Anna'] += 3
cnt['John'] += 2
cnt['Anna'] += 4
print(cnt)
=> Counter({'Anna': 7, 'John': 2})
print(cnt['Mario'])
=> 0
What is the equivalent of Counter
in Ruby?
EDIT:
The Counter
class provides also the following mathematical operations and helper methods:
c = Counter(a=3, b=1)
d = Counter(a=1, b=2)
c + d
=> Counter({'a': 4, 'b': 3})
c - d
=> Counter({'a': 2})
c.most_common(1)
=> ['a']
Counter is a subclass of dict that's specially designed for counting hashable objects in Python. It's a dictionary that stores objects as keys and counts as values. To count with Counter , you typically provide a sequence or iterable of hashable objects as an argument to the class's constructor.
A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts.
Accessing Elements in Python Counter To get the list of elements in the counter we can use the elements() method. It returns an iterator object for the values in the Counter.
The question was about Python 2.7, but I mention that as of Python 3.2 Counter is faster, so as of 2012 (8 years ago).
cnt = Hash.new(0)
cnt["Anna"] += 3
cnt["John"] += 2
cnt["Anna"] += 4
cnt # => {"Anna" => 7, "John" => 2}
cnt["Mario"] #=> 0
c = {"a" => 3, "b" => 1}
d = {"a" => 1, "b" => 2}
c.merge(d){|_, c, d| c + d} # => {"a" => 4, "b" => 3}
c.merge(d){|_, c, d| c - d}.select{|_, v| v > 0} # => {"a" => 2}
c.max(1).map(&:first) # => ["a"]
Here's a small implementation:
class Counter < Hash
def initialize(other = nil)
super(0)
if other.is_a? Array
other.each { |e| self[e] += 1 }
end
if other.is_a? Hash
other.each { |k,v| self[k] = v }
end
if other.is_a? String
other.each_char { |e| self[e] += 1 }
end
end
def +(rhs)
raise TypeError, "cannot add #{rhs.class} to a Counter" if ! rhs.is_a? Counter
result = Counter.new(self)
rhs.each { |k, v| result[k] += v }
result
end
def -(rhs)
raise TypeError, "cannot subtract #{rhs.class} to a Counter" if ! rhs.is_a? Counter
result = Counter.new(self)
rhs.each { |k, v| result[k] -= v }
result
end
def most_common(n = nil)
s = sort_by {|k, v| -v}
return n ? s.take(n) : s
end
def to_s
"Counter(#{super.to_s})"
end
def inspect
to_s
end
end
It supports
most_common
element(s)
c1 = Counter.new([1,0,1]) #=> Counter({1=>2, 0=>1})
c1[2] = 1 #=> 1
c1 #=> Counter({1=>2, 0=>1, 2=>1})
c2 = Counter.new([3,1]) #=> Counter({3=>1, 1=>1})
c1 + c2 #=> {1=>3, 0=>1, 2=>1, 3=>1}
c3 = Counter.new("abraca") #=> {"a"=>3, "b"=>1, "r"=>1, "c"=>1}
c3.most_common(2) #=> [["a", 3], ["b", 1]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With