Swift dizisindeki elemanların toplamını bulma


229

Hızlı bir tamsayı dizisinin toplamını bulmanın en kolay (en iyi) yolu nedir? Ben katları adlı bir dizi var ve ben katları toplamı bilmek istiyorum.

Yanıtlar:


467

Bu, bulabildiğim en kolay / en kısa yöntem.

Swift 3 ve Swift 4:

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

Hızlı 2:

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

Biraz daha bilgi:

Bu, Array'ın "sağlanan kapatmayı yinelemeli olarak uygulayarak bir öğe koleksiyonunu tek bir değere indirmenize izin veren" azaltma yöntemini ( buradaki belgeler ) kullanır . Başlangıç ​​değeri olarak 0 ve sonra esasen kapanış olarak veriyoruz { $0 + $1 }. Tabii ki, bunu tek bir artı işaretine sadeleştirebiliriz, çünkü Swift böyle işliyor.


42
Bu cevap için teşekkürler. Harika çalışıyor ve sadece özel sınıflar dizisi ile örnek kodumu eklemek istiyorum:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal

2
Harika yanıt ama eksik parametre adı combine. Olmalı multiples.reduce(0, combine: +).
Evgenii

2
For döngüsünden daha hızlı mı?
lorenzo

1
@SwiftMatt flatMapTek bir boyut dizisine düzleştirmek için önce üzerinde bir kullanmayı deneyin . multiArray.flatMap{$0}.reduce(0, combine: +)
Samah

2
@lorenzo - En son Swift ve XCode (UInt32 taşmasını önlemek için 256 ile kapatılan 1.000.000 UInt32 rasgele değerlerle dolu basit bir dizi) ile iPhone 7'de test yapmak, 'for' döngüsünün sadece saçın daha hızlı olduğunu gösterir (1.941 saniye ve 2.137 saniye) ancak bu avantaj 100.000 değerde (her biri 0.23 saniye) mevcut olmamasına rağmen . IMHO, kod netliği, 32 MB dizilerle uğraşırken bile çok küçük bir performans maliyetine değer.
Tom Dibble

86

Nesnelerin özelliklerini toplamak için 3+ bir astar çevirin

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

Noktaları azaltmaya çalıştığım benim özel nesne scaleData özelliği nerede


28

Swift3 şu şekilde değiştirildi:

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

22

In Swift 4 Ayrıca etmek dizisi elemanlarını kısıtlayabilir Sayısal aşağıdaki gibi dizideki tüm öğelerin toplamı dönmek için protokol

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

düzenleme / güncelleme:

Xcode 10.2 • Swift 5 veya üstü

Koleksiyondaki tüm öğelerin toplamını döndürmek için dizi öğelerini yeni AdditiveArithmetic protokolüyle kısıtlayabiliriz

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

Xcode 11 • Swift 5.1 veya üstü

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
Harika, güzel bir çözüm!
sabiland

11

Bu ayrıca işe yarar:

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

Sonuç: 55


10

Swift 4 örneği

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

Hızlı 3

Bir dizi genel nesneniz varsa ve bazı nesne özelliklerini toplamak istiyorsanız:

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 

Kısa forma rağmen, birçok kez klasik çevrim için tercih edebilirsiniz:

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, işte benim çözümüm: array.map ({$ 0.value}). azaltın (0, +)
Ivailo Kanev

Bu şekilde daha fazla kod yazar ve karmaşıklığı artırırsınız. Öyleyse, neden?
Luca Davanzo

6

Nasıl basit yolu hakkında

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

// burada n = dizideki öğe sayısı


Swift 3'te bunun artık geçerli olmadığına dikkat edin, çünkü döngüler için C stili dilden kaldırılmıştır. Bunun yerine for-in döngülerini kullanın, Swift indeksin dahili kaydını tutar.
donarb

1
Bu işe yaramaz. İlk önce toplamı 0 olarak başlatmalısınız. Azaltmanın güzelliği, size ilk değeri düşünmenizi hatırlatmasıdır.
MarkAurelius

var sum = 0 ; for n in multiples { sum += n }Her ne kadar azaltmak kullanın.
JeremyP

2

Olası bir çözüm: bunun için bir önek operatörü tanımlayın. APL'deki gibi "+ /" azaltma operatörü gibi (örn. GNU APL)

Burada biraz farklı bir yaklaşım var.

Bir protokol türü genel türü kullanmak, bu işleci Double, Float ve Int dizi türlerinde kullanmamızı sağlar

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
   }
}

şöyle kullanın:

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 için güncellendi, Xcode Sürüm 7.3'te test edildi)


Bununla ilgili bir sorun, genellikle (en azından büyük dizilerle uğraşırken) toplamın bileşenlerden farklı bir tür olması gerektiğidir. Örneğin, gamı ​​0 ile 2 ^ 32-1 arasında (örneğin arc4random () ile doldurulmuş) çalıştıran bir milyon UInt32'niz varsa, bunları eklemek her zaman UInt32 "toplam" değerinizi aşacaktır.
Tom Dibble

2

Swift 3.0

Ben aynı sorunu vardı, ben Apple bu çözüm belgelerinde bulundu.

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

Ama, benim durumumda bir nesne listesi vardı, o zaman benim listemdeki değeri dönüştürmek gerekiyordu:

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

bu iş benim için.


0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

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

Bunu iç içe parametreler için kullandı


0

Basit tutun ...

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)")

Çıktı:

Eleman toplamı: 37


0

Benim için bu özelliği kullanmak gibiydi

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

-2

Hızlı 3

Burada görüntülenen tüm seçeneklerden, bu benim için işe yaradı.

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


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

Bu sadece başka bir cevabın kopyası
Ashley Mills

-2

Nesneler dizisindeki öğelerin toplamı için

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

-4

bu benim yaklaşımım. Ancak inanıyorum ki en iyi çözüm tbd kullanıcı adının cevabı

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.