通过散列哈希迭代将元素转换为数组

时间:2018-06-15 03:20:28

标签: ruby

我正在处理从GitHub处理Webhook的响应。响应包含一个类似于此

的哈希web_hook_response
{:commits=>
  {:modified=>
    ["public/en/landing_pages/dc.json",
     "draft/en/landing_pages/careers/ac123.json"]
  }
}

现在我有一个处理这个哈希的函数。

 modified_or_deleted_files = []
 web_hook_response[:commits].map do |commit|
     modified_or_deleted_files << commit[:removed] << commit[:modified]
 end

我收到此错误

TypeError: no implicit conversion of Symbol into Integer

我试图找出commit在地图块内的价值,这就是打印的内容

[:modified,
 ["public/en/landing_pages/dc.json",
  "draft/en/landing_pages/careers/ac123.json"]]

为什么modified哈希转换为地图块内的符号数组和数组?我无法解释为什么会这样。任何人都可以解释为什么会这样吗?

3 个答案:

答案 0 :(得分:1)

web_hook_response[:commits]是一个哈希,而不是一个数组,所以当你在它上面调用map时,块参数commit会得到键值对,它是大小为2的数组。 / p>

我认为你需要的是连接2个数组。你可以

modified_or_deleted_files = web_hook_response[:commits].slice(:modified, :removed).values.flatten

答案 1 :(得分:1)

数据

这是你给出的哈希(稍微简化)。

web_hook_response = {
  :commits => { :modified => ["public", "draft"] }
}

它有一个键值对,键是:commits,值是哈希值

{ :modified => ["public", "draft"] }

本身有一个键(:modified)和一个值(["public", "draft"])。

错误

试试这个(我对web_hook_response的定义):

web_hook_response[:commits].map do |commit|
  puts "commit = #{commit}"
  modified_or_deleted_files << commit[:removed] << commit[:modified] # line 397
end
  # commit = [:modified, ["public", "draft"]]
  # TypeError: no implicit conversion of Symbol into Integer
    from (irb):397:in `[]'
    from (irb):397:in `block in irb_binding'
    from (irb):395:in `each'
    from (irb):395:in `map'

请注意,commit等于散列web_hook_response[:commits]中的键值对。如您所见,尝试计算

commit[:removed]
  #=> [:modified, ["public", "draft"]][:removed]

是传统表达式的句法糖形式

[:modified,  ["public", "draft"]].[](:removed)

由于[:modified, ["public", "draft"]]是一个数组,Array#[]是类Array的实例方法。 (是的,它是一个方法的有趣名称,但它是什么。)正如其文档中所解释的,方法的参数必须是整数,即元素的索引要返回的数组的数量。因此,当Ruby发现参数是符号(:removed)时,她会引发异常,&#34;没有将符号隐式转换为整数&#34;

计算modified_or_deleted_files

根据密钥:commits:modified,我们可以提取哈希

h = web_hook_response[:commits]
  #=> { :modified=>["public", "draft"] }

并从中提取数组

a = h[:modified]
  #=> ["public", "draft"]

我们通常将这两个操作链接起来以在一个语句中获取数组。

web_hook_response[:commits][:modified]
  #=> ["public", "draft"]

看起来您只想将变量modified_or_deleted_files的值设置为此数组,因此只需编写以下内容即可。

modified_or_deleted_files = web_hook_response[:commits][:modified]
  #=> ["public", "draft"]

答案 2 :(得分:1)

您的:commits是哈希值。在迭代哈希时,通常使用两个块参数,一个用于键,一个用于值,例如:

{ :foo => 'bar' }.each do |key, value|
  puts "#{key} = #{value}"
}
# outputs:
# foo = bar

当您只使用一个块参数时,您将获得一个数组中的键值对:

{ :foo => 'bar' }.each do |pair|
  puts pair.inspect
end
# outputs:
# [:foo, "bar"]

在您的示例中,您可以这样做:

commits = web_hook_response[:commits]
modified_or_deleted_files = Array(commits[:removed]) + Array(commits[:modified])

(如果Array(...)commits[:removed]commits[:modified]nil用于避免错误。Array(nil)返回空数组Array(an_array)返回数组)

或者,如果你想了解枚举器,迭代器等:

modified_or_deleted_files = web_hook_response[:commits].
  values_at(:modified, :removed). 
  compact. 
  reduce(:+)