ฉันมีอาร์เรย์ของจำนวนเต็ม
ตัวอย่างเช่น:
array = [123,321,12389]
มีวิธีที่ดีที่จะได้รับผลรวมของพวกเขา?
ฉันรู้แล้ว
sum = 0
array.each { |a| sum+=a }
จะทำงาน.
ฉันมีอาร์เรย์ของจำนวนเต็ม
ตัวอย่างเช่น:
array = [123,321,12389]
มีวิธีที่ดีที่จะได้รับผลรวมของพวกเขา?
ฉันรู้แล้ว
sum = 0
array.each { |a| sum+=a }
จะทำงาน.
คำตอบ:
ลองสิ่งนี้:
array.inject(0){|sum,x| sum + x }
(หมายเหตุ: 0
จำเป็นต้องใช้ตัวพิมพ์ใหญ่เพื่อ0
ส่งคืนอาร์เรย์ว่างเปล่าแทนnil
)
array.inject(:+)
มีประสิทธิภาพมากขึ้น
array.inject(:+)
ดูเหมือนว่าจะทำให้เกิดปัญหาใน Ruby 1.8.6 ข้อยกเว้น "LocalJumpError: ไม่มีบล็อกที่กำหนด" อาจปรากฏขึ้น
array.sum
อาจให้ผลรวมของค่าอาร์เรย์
reduce
ซึ่งเป็นนามแฝงของinject
(เหมือนในarray.reduce( :+ )
)
inject
reduce
หรือลองใช้วิธี Ruby 1.9:
array.inject(0, :+)
หมายเหตุ: 0
กรณีฐานเป็นสิ่งจำเป็นมิฉะนั้นnil
จะถูกส่งกลับในอาร์เรย์ที่ว่างเปล่า:
> [].inject(:+)
nil
> [].inject(0, :+)
0
array.map(&:price).inject(0, :+)
ปลอดภัยกว่านิดหน่อย มันทำให้แน่ใจว่าถ้าคุณมีรายการที่ว่างเปล่าที่คุณได้รับ0แทนศูนย์
array.inject(0) { |sum, product| sum += product.price }
array.reduce(0, :+)
ในขณะที่เทียบเท่ากับarray.inject(0, :+)
คำว่าลดกำลังเข้าสู่พื้นถิ่นที่พบบ่อยมากขึ้นด้วยการเพิ่มขึ้นของการเขียนโปรแกรม MapReduce รุ่น
ฉีด , ลด , พับ , สะสมและการบีบอัดที่มีความหมายเหมือนกันทั้งหมดเป็นชั้นของฟังก์ชั่นพับฟังก์ชั่นพับฉันพบว่าความสม่ำเสมอของรหัสฐานของคุณสำคัญที่สุด แต่เนื่องจากชุมชนต่าง ๆ มักจะชอบมากกว่าคำเดียวมันจึงมีประโยชน์ที่จะรู้ทางเลือกอื่น
เพื่อเน้นแผนที่ลดการใช้คำฟุ่มเฟือยนี่เป็นรุ่นที่ให้อภัยสิ่งที่เกิดขึ้นในอาเรย์นั้นเล็กน้อย
array.map(&:to_i).reduce(0, :+)
การอ่านที่เกี่ยวข้องเพิ่มเติมบางส่วน:
reduce
บอกฉันมากกว่าสิ่งที่ฟังก์ชั่นทำ แต่inject
เสียงเย็นกว่ามาก
reduce
และmap
ฟังก์ชั่นที่สูงกว่าการสั่งซื้อก่อนวันจริง MapReduce แรงบันดาลใจวิ่งไปทางอื่น และในแง่ของ MapReduce มันเป็นการดำเนินการที่แตกต่างจากการลดฟังก์ชันการทำงานอย่างง่ายโดยมีความหมายว่าเครื่องต่างกันอย่างไร
อีกทางเลือกหนึ่ง (สำหรับการเปรียบเทียบเท่านั้น) หากคุณติดตั้ง Rails (จริงๆแล้วเป็นแค่ ActiveSupport):
require 'activesupport'
array.sum
require 'active_support/core_ext/enumerable.rb'
require 'active_support/all'
เพิ่มเติมเกี่ยวกับที่นี่: เอกสาร API
activesupport
เป็นขนาดใหญ่พึ่งพาลากเข้าไปในโครงการที่จะไปจากการarray.inject(:+)
array.sum
require 'active_support/core_ext/enumerable'
โดยไม่ต้องมี.rb
คำต่อท้ายเนื่องจากมีการเพิ่มโดยนัย
สำหรับ Ruby> = 2.4.0 คุณสามารถใช้sum
จาก Enumerables
[1, 2, 3, 4].sum
มันเป็นอันตรายต่อคลาสฐาน mokeypatch หากคุณชอบอันตรายและใช้ Ruby รุ่นเก่ากว่าคุณสามารถเพิ่มลง#sum
ในArray
คลาสได้
class Array
def sum
inject(0) { |sum, x| sum + x }
end
end
Enumerable#sum
คุณสามารถใช้วิธีการตั้งชื่อเหมาะเจาะ มันมีข้อดีมากกว่าinject(:+)
แต่มีโน้ตสำคัญที่ต้องอ่านในตอนท้ายเช่นกัน
(1..100).sum
#=> 5050
[1, 2, 4, 9, 2, 3].sum
#=> 21
[1.9, 6.3, 20.3, 49.2].sum
#=> 77.7
#inject(:+)
วิธีการนี้จะไม่เทียบเท่ากับ ตัวอย่างเช่น
%w(a b c).inject(:+)
#=> "abc"
%w(a b c).sum
#=> TypeError: String can't be coerced into Integer
นอกจากนี้
(1..1000000000).sum
#=> 500000000500000000 (execution time: less than 1s)
(1..1000000000).inject(:+)
#=> 500000000500000000 (execution time: upwards of a minute)
ดูคำตอบนี้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสาเหตุที่sum
เป็นเช่นนี้
เพื่อความหลากหลายคุณสามารถทำได้ถ้าอาร์เรย์ของคุณไม่ใช่อาร์เรย์ของตัวเลข แต่เป็นอาร์เรย์ของวัตถุที่มีคุณสมบัติที่เป็นตัวเลข (เช่นจำนวน):
array.inject(0){|sum,x| sum + x.amount}
array.map(&:amount).inject(0, :+)
. ดูคำตอบอื่น ๆ
map
แล้วinject
คุณจะต้องห่วงผ่านอาร์เรย์สองครั้งเพื่อสร้างอาร์เรย์ใหม่อื่น ๆ ที่จะสรุปสมาชิก วิธีนี้ค่อนข้างละเอียดกว่าเล็กน้อย แต่ก็มีประสิทธิภาพมากกว่าด้วย
Ruby 2.4+ / Rails - array.sum
เช่น[1, 2, 3].sum # => 6
ทับทิมก่อน 2.4 - array.inject(:+)
หรือarray.reduce(:+)
* หมายเหตุ: #sum
วิธีนี้เป็นส่วนเสริมใหม่สำหรับ 2.4 enumerable
ดังนั้นตอนนี้คุณจะสามารถใช้array.sum
ในทับทิมบริสุทธิ์ไม่ใช่แค่ Rails
ruby 1.8.7 way เป็นดังต่อไปนี้:
array.inject(0, &:+)
คุณสามารถใช้:
example = [1,2,3]
example.inject(:+)
inject(:+)
แต่นี้ไม่ได้inject :+
?
นี่เพียงพอแล้ว
[1,2,3].inject('+')
ทับทิม 2.4.0 ถูกปล่อยออกมาและมันก็มี# รวม Enumerableวิธี ดังนั้นคุณสามารถทำได้
array.sum
ตัวอย่างจากเอกสาร:
{ 1 => 10, 2 => 20 }.sum {|k, v| k * v } #=> 50
(1..10).sum #=> 55
(1..10).sum {|v| v * 2 } #=> 110
ยังอนุญาตให้[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
สำหรับอาร์เรย์ที่มีค่าศูนย์เราสามารถทำขนาดกะทัดรัดแล้วฉีดผลรวม
a = [1,2,3,4,5,12,23.45,nil,23,nil]
puts a.compact.inject(:+)
array.reduce(:+)
ใช้งานได้สำหรับช่วงเช่นกัน ...
(1..10).reduce(:+) returns 55
ถ้าคุณรู้สึกว่ากอล์ฟคุณสามารถทำได้
eval([123,321,12389]*?+)
สิ่งนี้จะสร้างสตริง "123 + 321 + 12389" จากนั้นใช้ฟังก์ชัน eval เพื่อหาผลรวม นี่เป็นเพียงการเล่นกอล์ฟเท่านั้นคุณไม่ควรใช้รหัสนี้อย่างถูกต้อง
วิธีที่ 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
วิธีที่ 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 `+'
วิธีที่ 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 `+'
วิธีที่ 4: เมื่อ Array มีค่าศูนย์และค่าว่างโดยค่าเริ่มต้นหากคุณใช้ฟังก์ชันใด ๆ ข้างต้นลด, ผลรวม, ฉีดทุกอย่างจะผ่าน
TypeError: ไม่มีค่าบังคับใน Integer
คุณสามารถเอาชนะสิ่งนี้ได้โดย
[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
วิธีที่ 6: eval
หาค่านิพจน์ทับทิมในสตริง
[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+
3 วิธีที่เราสามารถทำผลรวมของอาร์เรย์
1) array.inject(0){|sum,x| sum + x }
2) array.inject('+')
3) array.join('+')
หรือคุณสามารถลองวิธีนี้:
def sum arr
0 if arr.empty
arr.inject :+
end
นี่เป็นวิธีที่สั้นที่สุด ลองมัน.
array.inject :+
number = [1..100]
number. each do |n|
final_number = n.sum
puts "The sum is #{final_number}"
end
* สิ่งนี้ทำงานได้ดีสำหรับฉันในฐานะนักพัฒนาใหม่ คุณสามารถปรับช่วงตัวเลขของคุณโดยการเปลี่ยนค่าภายใน []
คุณสามารถทำได้ง่ายๆ
def sum(numbers)
return 0 if numbers.length < 1
result = 0
numbers.each { |num| result += num }
result
end
คุณสามารถใช้. mapและ. sum ได้เช่น:
array.map { |e| e }.sum
array.sum
array.sum