涉及注入/方法和哈希的Ruby错误

时间:2015-01-04 01:21:05

标签: ruby

这是我的阵列:

array = [{:url=>"http://jumpstartlab.com/blog", :respondedIn=>37},
 {:url=>"http://jumpstartlab.com/blog", :respondedIn=>1},
 {:url=>"http://jumpstartlab.com/blog", :respondedIn=>11},
 {:url=>"http://jumpstartlab.com/about", :respondedIn=>11}]

这是我原来的方法:

array.inject(Hash.new(0)) {|hash, ele| hash[ele[:url]] += ele[:respondedIn]}

这是我的错误消息:

TypeError: no implicit conversion of String into Integer

这是我想要的回复:

{"http://jumpstartlab.com/blog"=>49, "http://jumpstartlab.com/about"=>11}

这是工作代码:

array.inject(Hash.new(0)) {|hash, ele| hash[ele[:url]] += ele[:respondedIn]; hash}

我原来的方法出了什么问题?为什么会抛出错误?

2 个答案:

答案 0 :(得分:1)

使用inject时,在第一次调用块之后,每次连续调用都会将前一个的返回值作为其累加器。所以你必须从块返回哈希:

array.inject(Hash.new(0)) {|hash, ele| hash[ele[:url]] += ele[:respondedIn]; hash}

您可以使用Hash#merge并避免块中的额外语句:

array.inject(Hash.new(0)) do |hash, ele| 
  hash.merge({ ele[:url] => hash[ele[:url]] +  ele[:respondedIn] })
end

或者,正如Cary Swoveland建议的那样,你可以使用each_with_object,它可以更清晰地处理可变累加器。请注意,它会在当前项之后将对象传递给块,而不是之前:

array.each_with_object(Hash.new 0) { |ele, hash| hash[ele[:url]] += ele[:respondedIn] }

任何这些都会产生您想要的结果:

# => {"http://jumpstartlab.com/blog"=>49, "http://jumpstartlab.com/about"=>11}

答案 1 :(得分:0)

在第一次尝试时,您没有返回注入块的正确值。进样块需要初始值的累计值(在您的情况下为Hash.new)作为返回值。 hash[ele[:url]] += ele[:respondedIn]语句不返回哈希值。我将通过一个例子展示其中的差异。

def first_try(hash,value)
  hash[value] += value
end

h1 = {1 => 1, 2 => 2}
first_try(h1,1) # => 2
first_try(h1,2) # => 4

在first_try中,我以与您在注入块中相同的方式返回最后一个语句。您可以检查返回值。它只是计算的结果。我没有收到哈希值。

def second_try(hash,value)
  hash[value] += value
  hash
end

h2 = {1 => 1, 2 => 2}
second_try(h2,1) # => {1=>2, 2=>2}
second_try(h2,2) # => {1=>2, 2=>4}

在第二次尝试中,我显式返回哈希值。所以我回来了。

您可以修改Mark Reed提到的代码,以避免显式返回。