Trovare la somma degli elementi nell'array Swift


228

Qual è il modo più semplice (migliore) per trovare rapidamente la somma di un array di numeri interi? Ho un array chiamato multipli e vorrei sapere la somma dei multipli.

Risposte:


466

Questo è il metodo più semplice / più breve che riesco a trovare.

Swift 3 e Swift 4:

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

Swift 2:

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

Qualche informazione in più:

Questo utilizza il metodo di riduzione di Array ( qui la documentazione ), che consente di "ridurre una raccolta di elementi fino a un singolo valore applicando in modo ricorsivo la chiusura fornita". Diamo 0 come valore iniziale e quindi, essenzialmente, la chiusura { $0 + $1 }. Certo, possiamo semplificarlo a un singolo segno più, perché è così che Swift rotola.


42
Grazie per questa risposta Funziona benissimo e voglio solo aggiungere il mio codice di esempio con un array di classi personalizzate:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal

2
Ottima risposta ma nome del parametro mancante combine. Dovrebbe essere multiples.reduce(0, combine: +).
Evgenii,

2
È più veloce di un ciclo for?
Lorenzo

1
@SwiftMatt Prova a usarlo flatMapprima per appiattirlo in un array a dimensione singola. multiArray.flatMap{$0}.reduce(0, combine: +)
Samah,

2
@lorenzo - Test su un iPhone 7 con Swift e XCode più recenti (un semplice array riempito con 1.000.000 di valori casuali UInt32 limitati a 256 per impedire il trabocco di UInt32) mostra in modo interessante che il ciclo 'for' è solo un pelo più veloce (1.941 secondi contro 2.137 secondi) , sebbene tale vantaggio non sia presente a 100.000 valori (0,23 secondi ciascuno). IMHO, la chiarezza del codice vale qualsiasi costo di prestazione molto piccolo qui anche quando si tratta di array da 32 MB.
Tom Dibble,

84

Swift 3+ una fodera per sommare le proprietà degli oggetti

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

Dove points è la proprietà nel mio oggetto personalizzato scaleData che sto cercando di ridurre


28

Swift3 è stato modificato in:

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

22

In Swift 4 Puoi anche vincolare gli elementi della sequenza al protocollo numerico per restituire la somma di tutti gli elementi nella sequenza come segue

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

Modifica / aggiornamento:

Xcode 10.2 • Swift 5 o successivo

Possiamo semplicemente vincolare gli elementi della sequenza al nuovo protocollo AdditiveArithmetic per restituire la somma di tutti gli elementi nella raccolta

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

Xcode 11 • Swift 5.1 o successivo

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
Ottima, bella soluzione!
sabiland,

11

Questo funziona anche:

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

Il risultato sarà: 55


10

Swift 4 esempio

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

Swift 3

Se si dispone di una matrice di oggetti generici e si desidera sommare alcune proprietà dell'oggetto, allora:

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 

Nonostante la forma più corta, molte volte potresti preferire il classico ciclo:

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, ecco la mia soluzione: array.map ({$ 0.value}). reduce (0, +)
Ivailo Kanev

In questo modo scrivi più codice e incrementa la complessità .. quindi, perché?
Luca Davanzo,

6

Che ne dici del modo semplice di

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

// dove n = numero di elementi nella matrice


Nota che in Swift 3 questo non è più valido perché lo stile C per i loop è stato rimosso dalla lingua. Utilizza invece i cicli for-in, Swift tiene traccia internamente dell'indice.
Donarb,

1
Non funzionerebbe così. Devi prima inizializzare la somma a 0. Il bello di ridurre è che ti ricorda di pensare al valore iniziale.
Marco Aurelio

var sum = 0 ; for n in multiples { sum += n }anche se vorrei usare ridurre.
JeremyP

2

Una possibile soluzione: definire un operatore prefisso per esso. Come l'operatore "+ /" ridotto come in APL (ad es. GNU APL)

Un approccio un po 'diverso qui.

L'uso di un protocollo di tipo generico ci consente di utilizzare questo operatore su tipi di array Double, Float e 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
   }
}

usare così:

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

(aggiornato per Swift 2.2, testato in Xcode versione 7.3)


Un problema è che spesso (almeno, quando si ha a che fare con array di grandi dimensioni) è necessario che la somma sia di un tipo diverso rispetto ai componenti. Ad esempio, se hai un milione di UInt32 che eseguono la gamma da 0 a 2 ^ 32-1 (ad es., Popolato da arc4random ()), l'aggiunta di questi eccederà ogni volta il tuo valore "somma" di UInt32.
Tom Dibble,

2

Swift 3.0

ho avuto lo stesso problema, ho trovato sulla documentazione Apple questa soluzione.

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

Ma, nel mio caso, avevo un elenco di oggetti, quindi avevo bisogno di trasformare il mio valore del mio elenco:

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

questo lavoro per me.


0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

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

usato questo per i parametri nidificati


0

Keep it simple ...

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

Produzione:

La mia somma di elementi è: 37


0

Per me, è stato così usando la proprietà

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

-2

Swift 3

Tra tutte le opzioni visualizzate qui, questa è quella che ha funzionato per me.

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


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

Questa è solo una copia di un'altra risposta
Ashley Mills,

-2

Per la somma degli elementi nella matrice di oggetti

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

-4

questo è il mio approccio al riguardo. tuttavia credo che la migliore soluzione sia la risposta dell'utente tbd

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.