Tôi có một loạt các số nguyên.
Ví dụ:
array = [123,321,12389]
Có cách nào hay để lấy tổng của chúng không?
Tôi biết điều đó
sum = 0
array.each { |a| sum+=a }
sẽ làm việc
Tôi có một loạt các số nguyên.
Ví dụ:
array = [123,321,12389]
Có cách nào hay để lấy tổng của chúng không?
Tôi biết điều đó
sum = 0
array.each { |a| sum+=a }
sẽ làm việc
Câu trả lời:
Thử cái này:
array.inject(0){|sum,x| sum + x }
(lưu ý: 0
trường hợp cơ sở là cần thiết để nó 0
sẽ được trả về trên một mảng trống thay vì nil
)
array.inject(:+)
là hiệu quả hơn.
array.inject(:+)
dường như gây ra sự cố trong Ruby 1.8.6 Ngoại lệ "LocalJumpError: không có khối nào được đưa ra" có thể bật lên.
array.sum
có thể cung cấp cho bạn tổng của các giá trị mảng.
reduce
, đó là bí danh của inject
(như trong array.reduce( :+ )
).
inject
chứ không phải reduce
.
Hoặc thử cách Ruby 1.9:
array.inject(0, :+)
Lưu ý: 0
trường hợp cơ sở là cần thiết nếu không nil
sẽ được trả về trên các mảng trống:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
an toàn hơn một chút Nó đảm bảo rằng nếu bạn có một danh sách trống, bạn nhận được 0 thay vì không .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Trong khi tương đương với array.inject(0, :+)
, thuật ngữ giảm đang bước vào một ngôn ngữ phổ biến hơn với sự gia tăng của các mô hình lập trình MapReduce .
tiêm , giảm , gấp , tích lũy và nén đều đồng nghĩa như một lớp các hàm gấp . Tôi thấy tính nhất quán trong cơ sở mã của bạn là quan trọng nhất, nhưng vì các cộng đồng khác nhau có xu hướng thích một từ hơn một từ khác, dù sao cũng hữu ích khi biết các lựa chọn thay thế.
Để nhấn mạnh thông số giảm bản đồ, đây là phiên bản dễ tha thứ hơn một chút về những gì kết thúc trong mảng đó.
array.map(&:to_i).reduce(0, :+)
Một số bài đọc liên quan bổ sung:
reduce
cho tôi biết nhiều hơn những gì chức năng làm, nhưng inject
âm thanh mát hơn nhiều.
reduce
và map
khi các hàm bậc cao hơn có trước MapReduce. Cảm hứng chạy theo cách khác. Và theo nghĩa MapReduce, đó là một hoạt động hơi khác so với giảm chức năng đơn giản, có ý nghĩa đối với cách các máy khác nhau giao tiếp.
Ngoài ra (chỉ để so sánh), nếu bạn đã cài đặt Rails (thực ra chỉ là ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
, hoặc yêu cầu tất cả hỗ trợ tích cực : require 'active_support/all'
. Thông tin thêm về nó ở đây: API Docs
activesupport
là một đồ sộ phụ thuộc để kéo vào một dự án để đi từ array.inject(:+)
đến array.sum
.
require 'active_support/core_ext/enumerable'
không có .rb
hậu tố, vì đó được thêm vào ngầm.
Đối với Ruby> = 2.4.0, bạn có thể sử dụng sum
từ Enumerables.
[1, 2, 3, 4].sum
Nó là nguy hiểm cho các lớp cơ sở mokeypatch. Nếu bạn thích nguy hiểm và sử dụng phiên bản cũ hơn của Ruby, bạn có thể thêm #sum
vào Array
lớp:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Bạn có thể sử dụng phương pháp được đặt tên khéo léo Enumerable#sum
. Nó có rất nhiều lợi thế hơn inject(:+)
nhưng cũng có một số lưu ý quan trọng để đọc ở cuối.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Phương pháp này không tương đương với #inject(:+)
. Ví dụ
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
Cũng thế,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
Xem câu trả lời này để biết thêm thông tin về lý do tại sao sum
như thế này.
Ruby 2.4+ / Rails - array.sum
tức là[1, 2, 3].sum # => 6
Ruby trước 2.4 - array.inject(:+)
hoặcarray.reduce(:+)
* Lưu ý: #sum
Phương pháp này là một bổ sung mới cho 2.4 enumerable
vì vậy bây giờ bạn sẽ có thể sử dụng array.sum
trong ruby nguyên chất, không chỉ Rails.
Chỉ vì mục đích đa dạng, bạn cũng có thể làm điều này nếu mảng của bạn không phải là một mảng số, mà là một mảng các đối tượng có các thuộc tính là số (ví dụ: số lượng):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. Xem câu trả lời khác.
map
sau đó inject
yêu cầu bạn lặp qua mảng hai lần: một lần để tạo một mảng mới, lần khác để tổng hợp các thành viên. Phương pháp này dài dòng hơn một chút, nhưng cũng hiệu quả hơn.
Cách ruby 1.8.7 là như sau:
array.inject(0, &:+)
Bạn chỉ có thể sử dụng:
example = [1,2,3]
example.inject(:+)
inject(:+)
nhưng điều này không inject :+
?
Thế là đủ
[1,2,3].inject('+')
Cũng cho phép [1,2].sum{|x| x * 2 } == 6
:
# http://madeofcode.com/posts/74-ruby-core-extension-array-sum
class Array
def sum(method = nil, &block)
if block_given?
raise ArgumentError, "You cannot pass a block and a method!" if method
inject(0) { |sum, i| sum + yield(i) }
elsif method
inject(0) { |sum, i| sum + i.send(method) }
else
inject(0) { |sum, i| sum + i }
end
end
end
Cách 1:
[1] pry(main)> [1,2,3,4].sum
=> 10
[2] pry(main)> [].sum
=> 0
[3] pry(main)> [1,2,3,5,nil].sum
TypeError: nil can't be coerced into Integer
Cách 2:
[24] pry(main)> [].inject(:+)
=> nil
[25] pry(main)> [].inject(0, :+)
=> 0
[4] pry(main)> [1,2,3,4,5].inject(0, :+)
=> 15
[5] pry(main)> [1,2,3,4,nil].inject(0, :+)
TypeError: nil can't be coerced into Integer
from (pry):5:in `+'
Cách 3:
[6] pry(main)> [1,2,3].reduce(:+)
=> 6
[9] pry(main)> [].reduce(:+)
=> nil
[7] pry(main)> [1,2,nil].reduce(:+)
TypeError: nil can't be coerced into Integer
from (pry):7:in `+'
Phương pháp 4: Khi Mảng chứa một giá trị nil và rỗng, theo mặc định, nếu bạn sử dụng bất kỳ hàm nào ở trên, hãy giảm, tổng hợp mọi thứ sẽ thông qua
TypeError: nil không thể bị ép buộc vào Integer
Bạn có thể khắc phục điều này bằng cách,
[16] pry(main)> sum = 0
=> 0
[17] pry(main)> [1,2,3,4,nil, ''].each{|a| sum+= a.to_i }
=> [1, 2, 3, 4, nil, ""]
[18] pry(main)> sum
=> 10
Phương pháp 6: eval
Đánh giá (các) biểu thức Ruby trong chuỗi.
[26] pry(main)> a = [1,3,4,5]
=> [1, 3, 4, 5]
[27] pry(main)> eval a.join '+'
=> 13
[30] pry(main)> a = [1,3,4,5, nil]
=> [1, 3, 4, 5, nil]
[31] pry(main)> eval a.join '+'
SyntaxError: (eval):1: syntax error, unexpected end-of-input
1+3+4+5+
Đây là con đường ngắn nhất. Thử nó.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Điều này làm việc tốt cho tôi như là một nhà phát triển mới. Bạn có thể điều chỉnh phạm vi số của mình bằng cách thay đổi các giá trị trong []
Bạn cũng có thể làm điều đó một cách dễ dàng
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Bạn có thể sử dụng .map và .sum như:
array.map { |e| e }.sum
array.sum
array.sum