0

我需要自己写方法group_by。这是我到目前为止所拥有的:

module Enumerable
  def group_by(&b)
    solution = {}
    self.each {|key,val|
      b.call(var)
      solution = { key=> (val) }
    }
   end
end

ary = [1,2,3,4,5,6,7,8,9,10]

p ary.group_by() { |i| i%3 }

我不明白。我希望你能帮助我。

4

4 回答 4

3

除了发布解决方案之外,我不确定我还能如何提供帮助,但也许一些您觉得困难的描述可能会有所帮助?

我注意到的几个问题:

  • 当数组只有 1 时,您正在使用将两个参数传递到块中,值
  • 您调用var当前范围内不存在的块,也许您的意思是 val?
  • 您不检查新解决方案字典中是否已存在任何内容
  • 每次循环遍历数组中的新值时,都会覆盖解决方案字典

这是我想出的:

module Enumerable

  def group_by
    solution = {}
    each do |value|
      key = yield value
      if solution.key?(key)
        solution[key] << value
      else
        solution[key] = [value]
      end
    end
    solution
  end

end

ary = [1, 2, 3, 4, 5]
p ary.group_by { |i| i % 3 }

输出:

{1=>[1, 4], 2=>[2, 5], 0=>[3]}

您可能想检查是否已给出块以防有人试图错误地使用该函数,请考虑使用该语句unless block_given?,但也许您可以尝试自己实现它。

于 2013-05-22T12:50:35.530 回答
3
module Enumerable
  def group_by &b; inject({}){|h, e| (h[b.call(e)] ||= []).push(e); h} end
end

[1,2,3,4,5,6,7,8,9,10].group_by{|i| i % 3}
# => {1 => [1, 4, 7, 10], 2 => [2, 5, 8], 0 => [3, 6, 9]}
于 2013-05-22T12:57:11.513 回答
2

从我的反向移植宝石

module Enumerable
  def group_by
    return to_enum(:group_by) unless block_given?
    result = {}
    each do |o|
      key = yield(o)
      ary = result.fetch(key){ result[key] = [] }
      ary << o
    end
    result
  end
end

与迄今为止提出的所有解决方案相反,它通过了RubySpec

于 2013-05-22T15:38:55.713 回答
2

比较的另一种解决方案:

module Enumerable
  def group_by
    {}.tap do |group|
      each{ |value| (group[ yield(value) ] ||= []) << value }
    end
  end
end
  • 用于tap避免难看的模式

    thing = {}
    # do stuff with thing
    thing # return it
    
  • 用于||=创建尚未存在的新集合数组

或者:

module Enumerable
  def group_by
    Hash.new{ |h,k| h[k]=[] }.tap do |group|
      each{ |value| group[ yield(value) ] << value }
      group.default = nil # remove the default_proc when done
    end
  end
end
于 2013-05-22T13:10:11.417 回答