2012-12-14 35 views
22

Tôi gặp sự cố với cú pháp để giảm. Tôi có một băm có định dạng sau:Giảm giá trị băm

H = {"Key1" => 1, "Key2" => 2} 

Tôi muốn sử dụng giảm để tìm tổng các giá trị trong hàm này.

Something Giống như

H.reduce(0) {|memo, elem| memo+=elem} 

Tôi biết điều này là sai. Tôi không hiểu làm thế nào tôi có thể làm cho elem giá trị của băm.

+6

Thử: H.values.reduce (: +) –

+0

Cảm ơn! đã làm các trick – richsoni

Trả lời

27

Sử dụng Enumerable#reduce, nếu bạn là ok với nhận nil nếu băm sẽ xảy ra là trống:

H.values.reduce(:+) # => 3 
Hash.new.values.reduce(:+) # => nil 

Để có được một cách an toàn 0 khi băm rỗng, sử dụng:

H.values.reduce(0) { |sum,x| sum + x } # or... 
H.reduce(0) { |sum,(key,val)| sum + val } # ...if you need to inspect the key 

Dưới đây là một chuẩn mực nhanh chóng, cho đá. Lưu ý rằng nó dường như là nhanh hơn một chút để giảm chỉ các giá trị chứ không phải là các giá trị từ các cặp khóa/giá trị:

       user  system  total  real 
H.values.reduce(:+)  4.510000 0.080000 4.590000 ( 4.595229) 
H.values.reduce(0) {...} 4.660000 0.080000 4.740000 ( 4.739708) 
H.reduce(0) {...}   5.160000 0.070000 5.230000 ( 5.241916) 
require 'benchmark' 

size = 1_000 
hash = Hash[* Array.new(size*2) { rand } ] 

N=10_000 
Benchmark.bm(24) do |x| 
    x.report('H.values.reduce(:+)')  { N.times { hash.dup.values.reduce(:+) } } 
    x.report('H.values.reduce(0) {...}') { N.times { hash.dup.values.reduce(0) { |sum,x| sum + x } } } 
    x.report('H.reduce(0) {...}')  { N.times { hash.dup.reduce(0) { |sum,(_,v)| sum + v } } } 
end 
+0

Lưu ý rằng điều này không trả lại 0 nếu một băm rỗng. Bạn cần phải sử dụng phiên bản ghi nhớ bên dưới –

1
h = {"Key1" => 1, "Key2" => 2} 

h.values.inject(0){|f,v| f += v.to_i } 
# => 3 

hoặc

h.values.inject(:+) 
# => 3 
4

Hãy thử điều này:

H.reduce(0) { |memo, elem| memo += elem[1] } 

hoặc

H.reduce(0) { |memo, (key, value)| memo += value } 
+1

Tôi đã viết 'memo + value' để tránh cho phép mọi người nghĩ rằng việc cập nhật' memo' là hữu ích. – lkuty

64

Bạn có thể làm elem chứa giá trị thông qua việc tách nó lên trong 2 biến:

H.reduce(0) {|memo, (key, val)| memo += val} 
+10

+1 cho cú pháp proc arg (khóa, val) thú vị! – maerics

+1

điều này thật tuyệt đẹp. – jturolla

+3

Tôi đã viết 'memo + val' để tránh cho phép mọi người nghĩ rằng việc cập nhật' memo' rất hữu ích. – lkuty

1

tôi biết tôi đang khai quật này, nhưng nếu bạn xảy ra để sử dụng Rails, các .sum method có thể giúp:

H = {"Key1" => 1, "Key2" => 2} 
=> {"Key1"=>1, "Key2"=>2} 
> H.values.sum 
=> 3 

Advantage là nó trả về 0 trên băm rỗng:

> {}.values.sum 
=> 0 
> {}.values.reduce(:+) 
=> nil 

tôi nhận thấy đó là Rails cụ thể chỉ sau khi nhập câu trả lời này. Tôi biết OP không thêm thẻ Rails, nhưng tôi nhận thấy nó có thể hữu ích cho những người dừng lại.

Lưu ý rằng như của Ruby 2.4.0, .sum is now available.

+1

'.sum' hiện được triển khai trong Ruby 2.4 [Tổng số có thể đếm được] (https://ruby-doc.org/core-2.4.0/Enumerable.html#method-i-sum). – user3162553

+0

Tốt bắt, tôi đã thêm một lưu ý trong câu trả lời của tôi, cảm ơn! – astorije

Các vấn đề liên quan