การหาผลรวมขององค์ประกอบในอาร์เรย์ Swift


228

วิธีที่ง่ายที่สุด (ดีที่สุด) ในการหาผลรวมของอาร์เรย์ของจำนวนเต็มอย่างรวดเร็วคืออะไร? ฉันมีอาร์เรย์ที่เรียกว่าทวีคูณและฉันต้องการทราบผลรวมของทวีคูณ

คำตอบ:


466

นี่เป็นวิธีที่ง่ายที่สุด / สั้นที่สุดที่ฉันสามารถหาได้

Swift 3 และ Swift 4:

let multiples = [...]
let sum = multiples.reduce(0, +)
print("Sum of Array is : ", sum)

สวิฟท์ 2:

let multiples = [...]
sum = multiples.reduce(0, combine: +)

ข้อมูลเพิ่มเติมบางส่วน:

วิธีนี้ใช้วิธีการลดของ Array (เอกสารประกอบที่นี่ ) ซึ่งช่วยให้คุณ "ลดการรวบรวมองค์ประกอบลงไปเป็นค่าเดียวโดยใช้การปิดแบบซ้ำ ๆ ซ้ำ ๆ " เราจะให้มัน 0 { $0 + $1 }เป็นค่าเริ่มต้นแล้วเป็นหลักปิด แน่นอนว่าเราสามารถทำให้มันง่ายขึ้นด้วยเครื่องหมายบวกเพียงอย่างเดียวเพราะนั่นเป็นวิธีที่ Swift กลิ้ง


42
ขอบคุณสำหรับคำตอบนี้ มันใช้งานได้ดีและฉันแค่ต้องการเพิ่มโค้ดตัวอย่างของฉันกับอาเรย์ของคลาสที่กำหนดเอง:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal

2
คำตอบที่ดี combineแต่หายไปชื่อพารามิเตอร์ multiples.reduce(0, combine: +)ควรจะเป็น
Evgenii

2
มันเร็วกว่าลูปหรือไม่?
Lorenzo

1
@SwiftMatt ลองใช้ a flatMapบนก่อนเพื่อทำให้แบนเป็นอาร์เรย์ขนาดเดียว multiArray.flatMap{$0}.reduce(0, combine: +)
Samah

2
@lorenzo - ทดสอบ iPhone 7 ด้วย Swift และ XCode ล่าสุด (อาร์เรย์ที่เรียบง่ายที่เต็มไปด้วย 1,000,000 UInt32 ค่าสุ่มที่ปกคลุมที่ 256 เพื่อป้องกันการล้น UInt32) แสดงให้เห็นว่า 'for' loop เป็นเพียงเส้นผมได้เร็วขึ้น (1.941 วินาทีต่อ 2.137 วินาที) แม้ว่าข้อได้เปรียบนั้นจะไม่ปรากฏที่ 100,000 ค่า (แต่ละ 0.23 วินาที) IMHO ความชัดเจนของรหัสมีค่าน้อยมากเมื่อเทียบกับ 32MB อาเรย์
Tom Dibble

84

Swift 3+หนึ่งสายการบินเพื่อรวมคุณสมบัติของวัตถุ

var totalSum = scaleData.map({$0.points}).reduce(0, +)

ไหนจุดที่เป็นสถานที่ให้บริการในวัตถุของฉันเองscaleDataว่าฉันกำลังพยายามที่จะลด



22

ในSwift 4คุณยังสามารถ จำกัด องค์ประกอบลำดับไปยังโปรโตคอลตัวเลขเพื่อส่งคืนผลรวมขององค์ประกอบทั้งหมดในลำดับดังต่อไปนี้

extension Sequence where Element: Numeric {
    /// Returns the sum of all elements in the collection
    func sum() -> Element { return reduce(0, +) }
}

แก้ไข / ปรับปรุง:

Xcode 10.2 • Swift 5 หรือใหม่กว่า

เราสามารถ จำกัด องค์ประกอบลำดับให้กับโปรโตคอลAdditiveArithmeticใหม่เพื่อส่งคืนผลรวมขององค์ประกอบทั้งหมดในคอลเลกชัน

extension Sequence where Element: AdditiveArithmetic {
    func sum() -> Element {
        return reduce(.zero, +)
    }
}

Xcode 11 • Swift 5.1 หรือใหม่กว่า

extension Sequence where Element: AdditiveArithmetic {
    func sum() -> Element { reduce(.zero, +) }
}

let numbers = [1,2,3]
numbers.sum()    // 6

let doubles = [1.5, 2.7, 3.0]
doubles.sum()    // 7.2

1
ยอดเยี่ยมทางออกที่ดี!
sabiland

11

สิ่งนี้ยังใช้งานได้:

let arr = [1,2,3,4,5,6,7,8,9,10]
var sumedArr = arr.reduce(0, combine: {$0 + $1})
print(sumedArr)

ผลลัพธ์จะเป็น: 55


10

ตัวอย่างของ Swift 4

class Employee {
    var salary: Int =  0
    init (_ salary: Int){
        self.salary = salary
    }
}

let employees = [Employee(100),Employee(300),Employee(600)]
var sumSalary = employees.reduce(0, {$0 + $1.salary}) //1000

9

สวิฟท์ 3

หากคุณมีอาร์เรย์ของวัตถุทั่วไปและคุณต้องการที่จะรวมคุณสมบัติของวัตถุบางอย่างแล้ว:

class A: NSObject {
    var value = 0
    init(value: Int) {
       self.value = value
    }
}

let array = [A(value: 2), A(value: 4)]      
let sum = array.reduce(0, { $0 + $1.value })
//                           ^       ^
//                        $0=result  $1=next A object
print(sum) // 6 

แม้จะมีรูปแบบที่สั้นกว่า แต่หลายครั้งคุณอาจชอบคลาสสิกสำหรับวงจร:

let array = [A(value: 2), A(value: 4)]
var sum = 0
array.forEach({ sum += $0.value}) 
// or
for element in array {
   sum += element.value
}

1
ciao Luca นี่คือคำตอบของฉัน: array.map ({$ 0.value}). ลด (0, +)
Ivailo Kanev

ด้วยวิธีนี้คุณเขียนโค้ดเพิ่มเติมและเพิ่มความซับซ้อน .. ดังนั้นทำไม?
Luca Davanzo

6

วิธีการเกี่ยวกับวิธีง่ายๆ

for (var i = 0; i < n; i++) {
 sum = sum + Int(multiples[i])!
}

// โดยที่ n = จำนวนขององค์ประกอบในอาร์เรย์


โปรดทราบว่าใน Swift 3 จะไม่สามารถใช้งานได้อีกต่อไปเนื่องจากสไตล์ C สำหรับลูปถูกลบออกจากภาษา ใช้ for-in loops แทน Swift คอยติดตามภายในของดัชนี
donarb

1
ที่ไม่ทำงานตามที่ คุณต้องเริ่มต้นรวมเป็น 0 ก่อน ความงามของการลดความมันคือการเตือนให้คุณนึกถึงค่าเริ่มต้น
MarkAurelius

var sum = 0 ; for n in multiples { sum += n }แม้ว่าฉันจะใช้ลด
JeremyP

2

ทางออกที่เป็นไปได้: กำหนดตัวดำเนินการส่วนนำหน้าสำหรับมัน ชอบตัวดำเนินการลด "+ /" เช่นเดียวกับใน APL (เช่น GNU APL)

วิธีการที่แตกต่างกันเล็กน้อยที่นี่

การใช้โปรโตคอล en ประเภททั่วไปทำให้เราสามารถใช้โอเปอเรเตอร์นี้กับประเภท Double, Float และ Int

protocol Number 
{
   func +(l: Self, r: Self) -> Self
   func -(l: Self, r: Self) -> Self
   func >(l: Self, r: Self) -> Bool
   func <(l: Self, r: Self) -> Bool
}

extension Double : Number {}
extension Float  : Number {}
extension Int    : Number {}

infix operator += {}

func += <T:Number> (inout left: T, right: T)
{
   left = left + right
}

prefix operator +/ {}

prefix func +/ <T:Number>(ar:[T]?) -> T?
{
    switch true
    {
    case ar == nil:
        return nil

    case ar!.isEmpty:
        return nil

    default:
        var result = ar![0]
        for n in 1..<ar!.count
        {
            result += ar![n]
        }
        return result
   }
}

ใช้อย่างนั้น:

let nmbrs = [ 12.4, 35.6, 456.65, 43.45 ]
let intarr = [1, 34, 23, 54, 56, -67, 0, 44]

+/nmbrs     // 548.1
+/intarr    // 145

(อัปเดตสำหรับ Swift 2.2 ทดสอบใน Xcode เวอร์ชั่น 7.3)


ปัญหาอย่างหนึ่งของเรื่องนี้ก็คือบ่อยครั้ง (อย่างน้อยเมื่อจัดการกับอาร์เรย์ขนาดใหญ่) คุณจะต้องมีผลรวมเป็นประเภทที่แตกต่างจากส่วนประกอบ ตัวอย่างเช่นหากคุณมีล้าน UInt32s ที่ใช้โทนเสียงดนตรีจาก 0 ถึง 2 ^ 32-1 (เช่นมีประชากรโดย arc4random ()) การเพิ่มค่าเหล่านั้นจะทำให้ค่า "รวม" UInt32 ของคุณล้นทุกครั้ง
Tom Dibble

2

สวิฟท์ 3.0

ฉันมีปัญหาเดียวกันฉันพบในเอกสารของ Apple วิธีนี้

let numbers = [1, 2, 3, 4]
let addTwo: (Int, Int) -> Int = { x, y in x + y }
let numberSum = numbers.reduce(0, addTwo)
// 'numberSum' == 10

แต่ในกรณีของฉันฉันมีรายการวัตถุแล้วฉันต้องการเปลี่ยนมูลค่าของรายการ:

let numberSum = self.list.map({$0.number_here}).reduce(0, { x, y in x + y })

งานนี้สำหรับฉัน


0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

private var allFieldsCount: Int {
    var sum = 0
    valueSource.forEach { sum += $0.count }
    return sum
}

ใช้อันนี้สำหรับพารามิเตอร์ที่ซ้อนกัน


0

ง่าย ๆ เข้าไว้...

var array = [1, 2, 3, 4, 5, 6, 7, 9, 0]
var n = 0
for i in array {
    n += i
}
print("My sum of elements is: \(n)")

เอาท์พุท:

องค์ประกอบของฉันคือ: 37


0

สำหรับฉันมันเป็นเช่นนี้โดยใช้คุณสมบัติ

    let blueKills = match.blueTeam.participants.reduce(0, { (result, participant) -> Int in
        result + participant.kills
    })

-2

สวิฟท์ 3

จากตัวเลือกทั้งหมดที่แสดงที่นี่นี่เป็นตัวเลือกที่เหมาะกับฉัน

let arr = [6,1,2,3,4,10,11]


var sumedArr = arr.reduce(0, { ($0 + $1)})
print(sumedArr)

นี่เป็นเพียงสำเนาของคำตอบอื่น ๆ
แอชลีย์มิลส์

-2

สำหรับผลรวมขององค์ประกอบในอาร์เรย์ของวัตถุ

self.rankDataModelArray.flatMap{$0.count}.reduce(0, +)

-4

นี่คือแนวทางของฉันเกี่ยวกับเรื่องนี้ แต่ฉันเชื่อว่าทางออกที่ดีที่สุดคือคำตอบจากชื่อผู้ใช้ tbd

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.