我们可以通过使用默认值初始化哈希的键来解决以下问题吗?

时间:2019-07-12 03:44:07

标签: ruby

编写一种方法,使用“注入”将上述哈希值分为2个长度分别为“偶数”和“奇数”的组。 输入-“ ['abc','def','1234','234','abcd','x','mnop','5','zZzZ']”

下面列出的我的代码已经可以使用了。但是我想知道使用默认值作为哈希键的更好方法。我的意思是说如下-

h=Hash.new { |hash, key| hash[key] = []}

解决方案:

class Array
  def group_even_odd
    key_hash = group_by(&:length)
    key_array = %w(even odd)
    key_hash.each_with_object('odd' => [], 'even' => []) do |(key, value), even_odd_hash|
      even_odd_hash[key_array[key % 2]].push(value)
      even_odd_hash
    end
  end
end
if ARGV.empty?
  puts 'Please provide an input'
else
  input = ARGV[0].scan(/\w+/).map(&:to_s)
  puts input.group_even_odd
end

预期与实际相同,代码正在工作。

预期结果-
{“ odd” => [[“” abc“,” def“,” 234“],[” x“,” 5“]],” even“ => [[” 1234“,” abcd“,” mnop“ ,“ zZzZ”]]}

2 个答案:

答案 0 :(得分:1)

给出了一个可能的选择

ary = ["abc", "def", "1234", "234", "abcd", "x", "mnop", "5", "zZzZ"]

首先按偶数分组,然后按大小分组:

ary.group_by { |e| e.size.even? ? 'even' : 'odd' }
   .transform_values { |v| v.group_by(&:size).values }

#= {"odd"=>[["abc", "def", "234"], ["x", "5"]], "even"=>[["1234", "abcd", "mnop", "zZzZ"]]}


第一步,进行解释:

ary.group_by { |e| e.size.even? ? 'even' : 'odd' }
#=> {"odd"=>["abc", "def", "234", "x", "5"], "even"=>["1234", "abcd", "mnop", "zZzZ"]}

然后Hash#transform_values按大小分组。

答案 1 :(得分:0)

以下内容不符合使用inject(又名reduce)的要求,但这是我的方法。

arr = ['abc', 'def', '1234', '234', 'abcd', 'x', 'mnop', '5', 'zZzZ']

odd, even = arr.each_with_object(Hash.new { |h,k| h[k]=[] }) do |s,h|
  h[s.size] << s
end.
values.
partition { |a| a.first.size.odd? }
  #=> [[["abc", "def", "234"], ["x", "5"]],
  #    [["1234", "abcd", "mnop", "zZzZ"]]]
{ "odd"=>odd, "even"=>even }    
  #=> {"odd"=>[["abc", "def", "234"], ["x", "5"]],
  #    "even"=>[["1234", "abcd", "mnop", "zZzZ"]]}

步骤如下。

h = arr.each_with_object(Hash.new {|h,k| h[k]=[]}) do |s,h|
  h[s.size] << s
end
  #=> {3=>["abc", "def", "234"], 4=>["1234", "abcd", "mnop", "zZzZ"],
  #    1=>["x", "5"]} 
a = h.values
  #=> [["abc", "def", "234"], ["1234", "abcd", "mnop", "zZzZ"],
  #    ["x", "5"]]      
odd, even = a.partition { |a| a.first.size.odd? }
  #=> [[["abc", "def", "234"], ["x", "5"]],
  #    [["1234", "abcd", "mnop", "zZzZ"]]]
{ "odd"=>odd, "even"=>even }
  #=> {"odd"=>[["abc", "def", "234"], ["x", "5"]],
  #    "even"=>[["1234", "abcd", "mnop", "zZzZ"]]} 

如果有人坚持将方形钉插入圆形握持中(使用inject/reduce),我想可以这样做如下。

arr.reduce({ "odd"=>[], "even"=>[] }) do |g,s|
  oe = s.size.odd? ? "odd" : "even"
  i = g[oe].find_index { |a| a.any? && a.first.size == s.size }
  case i.nil?
  when true then g[oe] << [s]
  else g[oe][i] << s
  end
  g
end
  #=> {"odd"=>[["abc", "def", "234"], ["x", "5"]],
  #    "even"=>[["1234", "abcd", "mnop", "zZzZ"]]}