From: keystonelemur@... Date: 2019-01-29T01:05:01+00:00 Subject: [ruby-core:91312] [Ruby trunk Feature#11076] Enumerable method count_by Issue #11076 has been updated by baweaver (Brandon Weaver). mame (Yusuke Endoh) wrote: > I have learnt the word "tally" in this thread. Thank you. It looks good to me, a non-native speaker. I have put this on the agenda of the next developers' meeting. > > By the way, what is the precise semantics of the method? > > Question 1. What identity is the object in the keys? > > ``` > str1 = "a" > str2 = "a" > t = [str1, str2].tally > > p t #=> { "a" => 2 } > > p t.keys.first.object_id #=> str1.object_id or str2.object_id ? > ``` > > IMO: I think it should prefer the first element, so it should be equal to `str1.object_id`. > > Question 2. What is the key of `tally_by`? > > ``` > str1 = "a" > str2 = "A" > t = [str1, str2].tally_by(&:upcase) > > p t #=> { "a" => 2 } or { "A" => 2 } ? > > p t.keys.first.object_id #=> str1.object_id, str2.object_id, or otherwise? > ``` > > IMO: The return values of `sort_by` and `max_by` contains the original elements, not the return value of the block. According to the analogy to them, I think that `t` should be `{ "a" => 2 }` and its key be `str1.object_id`. Answer 1: I would say the first, but `tally` could also be effectively represented by `tally_by(&:itself)` as shown in an implementation below: Answer 2: The transformed value, like `group_by`: ``` [1, 2, 3].group_by(&:even?) => {false=>[1, 3], true=>[2]} [1, 2, 3].tally_by(&:even?) => {false => 2, true => 1} ``` The implementation is similar to this: ``` module Enumerable # Implementing via group_by def tally_by(&fn) group_by(&fn).to_h { |k, vs| [k, vs.size] } end # Implementing via reduction def tally_by2(&fn) each_with_object(Hash.new(0)) { |v, a| a[fn[v]] += 1 } end end ``` ...which would result in the first `object_id` I believe. ---------------------------------------- Feature #11076: Enumerable method count_by https://bugs.ruby-lang.org/issues/11076#change-76559 * Author: haraldb (Harald B��ttiger) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- I very often use `Hash[array.group_by{|x|x}.map{|x,y|[x,y.size]}]`. Would be nice with to have a method called `count_by`: ~~~ruby array = ['aa', 'aA', 'bb', 'cc'] p array.count_by(&:downcase) #=> {'aa'=>2,'bb'=>1,'cc'=>1} ~~~ -- https://bugs.ruby-lang.org/ Unsubscribe: