Znajdowanie sumy elementów w tablicy Swift


228

Jaki jest najłatwiejszy (najlepszy) sposób szybkiego znalezienia sumy tablic liczb całkowitych? Mam tablicę o nazwie wielokrotności i chciałbym poznać sumę wielokrotności.

Odpowiedzi:


466

To najłatwiejsza / najkrótsza metoda, jaką mogę znaleźć.

Swift 3 i Swift 4:

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

Swift 2:

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

Więcej informacji:

Wykorzystuje to metodę Array'a zmniejszania ( tutaj dokumentacja ), która pozwala „zmniejszyć zbiór elementów do jednej wartości poprzez rekurencyjne zastosowanie dostarczonego zamknięcia”. Dajemy mu 0 jako wartość początkową, a następnie zasadniczo zamknięcie { $0 + $1 }. Oczywiście możemy to uprościć do pojedynczego znaku plus, ponieważ tak właśnie działa Swift.


42
Dziękuję za tę odpowiedź. Działa świetnie i chcę tylko dodać mój przykładowy kod z tablicą niestandardowych klas:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal

2
Świetna odpowiedź, ale brak nazwy parametru combine. Powinno być multiples.reduce(0, combine: +).
Evgenii,

2
Czy to jest szybsze niż pętla for?
lorenzo

1
@ SwiftMatt Spróbuj użyć flatMapnajpierw go, aby spłaszczyć go do tablicy jednowymiarowej. multiArray.flatMap{$0}.reduce(0, combine: +)
Samah,

2
@lorenzo - Testowanie na iPhonie 7 z najnowszym Swift i XCode (prosta tablica wypełniona 1 000 000 losowych wartości UInt32 ograniczona do 256, aby zapobiec przepełnieniu UInt32), co ciekawe, pokazuje, że pętla „for” jest tylko o włos szybsza (1.941 sekundy w porównaniu do 2.137 sekund) , chociaż ta przewaga nie występuje przy 100 000 wartości (0,23 sekundy każda). IMHO, klarowność kodu jest tu warta bardzo niewielkiego kosztu wydajności, nawet w przypadku tablic 32 MB.
Tom Dibble,

84

Swift 3+ one liner, aby zsumować właściwości obiektów

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

Gdzie punkty są właściwością w moim niestandardowym obiekcie scaleData, który próbuję zmniejszyć



22

W Swift 4 możesz również ograniczyć elementy sekwencji do protokołu numerycznego , aby zwrócić sumę wszystkich elementów w sekwencji w następujący sposób

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

edycja / aktualizacja:

Xcode 10.2 • Swift 5 lub nowszy

Możemy po prostu ograniczyć elementy sekwencji do nowego protokołu AdditiveArithmetic , aby zwrócić sumę wszystkich elementów w kolekcji

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

Xcode 11 • Swift 5.1 lub nowszy

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
Świetne, fajne rozwiązanie!
sabiland

11

Działa to również:

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

Wynik będzie: 55


10

Przykład 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

Szybki 3

Jeśli masz tablicę obiektów ogólnych i chcesz zsumować niektóre właściwości obiektu, to:

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 

Pomimo krótszej formy wiele razy możesz preferować klasyczny cykl rowerowy:

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, oto moje rozwiązanie: array.map ({0,0 $ wartość)). redukcja (0, +)
Ivailo Kanev

W ten sposób piszesz więcej kodu i zwiększasz złożoność ... więc dlaczego?
Luca Davanzo

6

Co powiesz na prosty sposób

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

// gdzie n = liczba elementów w tablicy


Zauważ, że w Swift 3 nie jest to już prawidłowe, ponieważ styl C dla pętli został usunięty z języka. Zamiast tego używaj pętli for, Swift śledzi wewnętrznie indeks.
donarb

1
To by tak nie działało. Najpierw musisz zainicjować sumę na 0. Piękno redukcji polega na tym, że przypomina ona o początkowej wartości.
MarkAurelius

var sum = 0 ; for n in multiples { sum += n }chociaż użyłbym redukcji.
JeremyP

2

Możliwe rozwiązanie: zdefiniuj dla niego operatora prefiksu. Podobnie jak operator zmniejszania „+ /” jak w APL (np. GNU APL)

Trochę innego podejścia tutaj.

Użycie protokołu w typie ogólnym pozwala nam używać tego operatora w typach tablic Double, Float i 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
   }
}

użyj tak:

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

(zaktualizowany do Swift 2.2, przetestowany w Xcode w wersji 7.3)


Jednym z problemów jest to, że często (przynajmniej w przypadku dużych tablic) potrzebna będzie suma innego rodzaju niż komponenty. Na przykład, jeśli masz milion UInt32 obsługujących gamut od 0 do 2 ^ 32-1 (np. Wypełniony przez arc4random ()), dodanie ich spowoduje przepełnienie twojej wartości „sumy” UInt32 za każdym razem.
Tom Dibble,

2

Swift 3.0

miałem ten sam problem, znalazłem w dokumentacji Apple to rozwiązanie.

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

Ale w moim przypadku miałem listę obiektów, a następnie potrzebowałem przekształcić moją wartość mojej listy:

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

ta praca dla mnie.


0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

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

użył tego dla parametrów zagnieżdżonych


0

Nie komplikuj...

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

Wynik:

Moja suma elementów to: 37


0

Dla mnie było tak przy użyciu nieruchomości

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

-2

Szybki 3

Ze wszystkich wyświetlonych tutaj opcji ta działała dla mnie.

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


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

To tylko kopia innej odpowiedzi
Ashley Mills

-2

Dla sumy elementów w tablicy obiektów

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

-4

takie jest moje podejście do tego. jednak uważam, że najlepszym rozwiązaniem jest odpowiedź z nazwy użytkownika tbd

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.