我自己写方法group_by

时间:2013-05-22 12:19:08

标签: ruby group-by

我需要自己编写方法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 个答案:

答案 0 :(得分: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?,但也许您可以尝试自己实现。

答案 1 :(得分: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]}

答案 2 :(得分: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

答案 3 :(得分:2)

来自我的backports gem

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