Saya memiliki array bilangan bulat.
Sebagai contoh:
array = [123,321,12389]
Apakah ada cara yang bagus untuk mendapatkan jumlah mereka?
Saya tahu itu
sum = 0
array.each { |a| sum+=a }
akan bekerja.
Saya memiliki array bilangan bulat.
Sebagai contoh:
array = [123,321,12389]
Apakah ada cara yang bagus untuk mendapatkan jumlah mereka?
Saya tahu itu
sum = 0
array.each { |a| sum+=a }
akan bekerja.
Jawaban:
Coba ini:
array.inject(0){|sum,x| sum + x }
Lihat Dokumentasi Enumerable Ruby
(catatan: 0
case dasar diperlukan sehingga 0
akan dikembalikan pada array kosong bukan nil
)
array.inject(:+)
lebih efisien.
array.inject(:+)
tampaknya menyebabkan masalah di Ruby 1.8.6 Pengecualian "LocalJumpError: no block diberikan" mungkin muncul.
array.sum
mungkin memberi Anda jumlah nilai array.
reduce
, yang merupakan alias dari inject
(seperti pada array.reduce( :+ )
).
inject
daripada reduce
.
Atau coba cara Ruby 1.9:
array.inject(0, :+)
Catatan: 0
case dasar diperlukan jika tidak nil
akan dikembalikan pada array kosong:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
sedikit lebih aman. Itu memastikan bahwa jika Anda memiliki daftar kosong Anda mendapatkan 0 bukannya nihil .
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
Sementara setara dengan array.inject(0, :+)
, pengurangan kata memasuki bahasa yang lebih umum dengan munculnya model pemrograman MapReduce .
menyuntikkan , mengurangi , melipat , menumpuk , dan mengompres semuanya identik sebagai kelas fungsi lipat . Saya menemukan konsistensi di seluruh basis kode Anda yang paling penting, tetapi karena berbagai komunitas cenderung lebih suka satu kata dari yang lain, tetap berguna untuk mengetahui alternatifnya.
Untuk menekankan verbiage pengurangan peta, berikut adalah versi yang sedikit lebih memaafkan pada apa yang berakhir di array itu.
array.map(&:to_i).reduce(0, :+)
Beberapa bacaan tambahan yang relevan:
reduce
ceritakan lebih banyak tentang apa fungsinya, tetapi inject
terdengar lebih keren.
reduce
dan map
ketika fungsi tingkat tinggi mendahului MapReduce. Inspirasi berjalan sebaliknya. Dan dalam pengertian MapReduce, ini adalah operasi yang agak berbeda dari pengurangan fungsional sederhana, memiliki implikasi untuk bagaimana mesin yang berbeda berkomunikasi.
Atau (hanya untuk perbandingan), jika Anda memasang Rails (sebenarnya hanya ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
, atau memerlukan semua dukungan aktif: require 'active_support/all'
. Lebih lanjut tentang ini di sini: API Documents
activesupport
adalah besar ketergantungan untuk tarik ke sebuah proyek untuk pergi dari array.inject(:+)
ke array.sum
.
require 'active_support/core_ext/enumerable'
tanpa .rb
akhiran, karena ditambahkan secara implisit.
Untuk Ruby> = 2.4.0 Anda dapat menggunakan sum
dari Enumerables.
[1, 2, 3, 4].sum
Berbahaya untuk mokeypatch kelas dasar. Jika Anda suka bahaya dan menggunakan versi Ruby yang lebih lama, Anda bisa menambahkan #sum
ke Array
kelas:
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Anda dapat menggunakan metode yang dinamai tepat Enumerable#sum
. Ini memiliki banyak keunggulan dibandingkan inject(:+)
tetapi ada beberapa catatan penting untuk dibaca di akhir juga.
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
Metode ini tidak setara dengan #inject(:+)
. Sebagai contoh
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
Juga,
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
Lihat jawaban ini untuk informasi lebih lanjut tentang mengapa sum
seperti ini.
Ruby 2.4+ / Rails - array.sum
mis[1, 2, 3].sum # => 6
Ruby pre 2.4 - array.inject(:+)
atauarray.reduce(:+)
* Catatan: #sum
Metode ini merupakan tambahan baru untuk 2.4 enumerable
sehingga Anda sekarang dapat menggunakan array.sum
ruby murni, bukan hanya Rails.
Hanya demi keberagaman, Anda juga dapat melakukan ini jika array Anda bukan array angka, melainkan array objek yang memiliki properti yang berupa angka (misalnya jumlah):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. Lihat jawaban lain.
map
kemudian inject
mengharuskan Anda untuk mengulang array dua kali: sekali untuk membuat array baru, yang lain untuk menjumlahkan anggota. Metode ini sedikit lebih verbose, tetapi juga lebih efisien.
Cara ruby 1.8.7 adalah sebagai berikut:
array.inject(0, &:+)
Anda cukup menggunakan:
example = [1,2,3]
example.inject(:+)
inject(:+)
tetapi ini tidak inject :+
?
Ini cukup
[1,2,3].inject('+')
Ruby 2.4.0 dirilis, dan ia memiliki metode # jumlah Enumerable . Jadi kamu bisa melakukannya
array.sum
Contoh dari dokumen:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
Juga memungkinkan untuk [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
untuk array dengan nilai nil kita bisa melakukan compact dan kemudian menyuntikkan jumlah ex
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
Metode 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
Metode 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 `+'
Metode 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 `+'
Metode 4: Ketika Array berisi nihil dan nilai kosong, secara default jika Anda menggunakan fungsi di atas mengurangi, menjumlahkan, menyuntikkan semuanya akan melalui
TypeError: nil tidak bisa dipaksa menjadi Integer
Anda dapat mengatasi ini dengan,
[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
Metode 6: eval
Mengevaluasi ekspresi Ruby dalam string.
[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+
Ini jalan terpendek. Cobalah.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* Ini bekerja dengan baik untuk saya sebagai pengembang baru. Anda dapat menyesuaikan rentang angka dengan mengubah nilai dalam []
Anda juga bisa melakukannya dengan mudah
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
Anda dapat menggunakan .map dan .sum seperti:
array.map { |e| e }.sum
array.sum
array.sum