Method: Enumerable#tally

Defined in:
enum.c

#tally(hash = {}) ⇒ Hash

When argument hash is not given, returns a new hash whose keys are the distinct elements in self; each integer value is the count of occurrences of each element:

%w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}

When argument hash is given, returns hash, possibly augmented; for each element ele in self:

  • Adds it as a key with a zero value if that key does not already exist:

    hash[ele] = 0 unless hash.include?(ele)
    
  • Increments the value of key ele:

    hash[ele] += 1
    

This is useful for accumulating tallies across multiple enumerables:

h = {}                   # => {}
%w[a c d b c a].tally(h) # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1}
%w[b a z].tally(h)       # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1}
%w[b a m].tally(h)       # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=>1}

The key to be added or found for an element depends on the class of self; see Enumerable in Ruby Classes.

Examples:

  • Array (and certain array-like classes): the key is the element (as above).

  • Hash (and certain hash-like classes): the key is the 2-element array formed from the key-value pair:

    h = {}                        # => {}
    {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1}
    {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1, [:foo, "c"]=>1, [:bar, "d"]=>1}
    {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>1, [:bar, "d"]=>1}
    {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>2, [:bar, "d"]=>2}
    

Returns:



1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
# File 'enum.c', line 1282

static VALUE
enum_tally(int argc, VALUE *argv, VALUE obj)
{
    VALUE hash;
    if (rb_check_arity(argc, 0, 1)) {
        hash = rb_to_hash_type(argv[0]);
        rb_check_frozen(hash);
    }
    else {
        hash = rb_hash_new();
    }

    return enum_hashify_into(obj, 0, 0, tally_i, hash);
}