这是我的阵列:
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}
我原来的方法出了什么问题?为什么会抛出错误?
答案 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提到的代码,以避免显式返回。