def group_by_with(empty_group, &block)
      block ||= lambda { |item| item }
      return reduce(EmptyMap) do |map, item|
        key = block.call(item)
        group = map.get(key) || empty_group
        map.put(key, group.add(item))
      end
    end
def group_by_with(empty_group, &block)
      block ||= lambda { |item| item }
      return reduce(EmptyMap) do |map, item|
        key = block.call(item)
        group = map.get(key) || empty_group
        map.put(key, group.add(item))
      end
    end
Groups the collection into sub-collections by the result of yielding them to
 the block. Returns a {Map} where the keys are return values from the block,
 and the values are sub-collections. All the sub-collections are built up from
 `empty_group`, which should respond to `#add` by returning a new collection
 with an added element.