Localizando soma dos elementos no array Swift


228

Qual é a maneira mais fácil (melhor) de encontrar a soma de uma matriz de números inteiros rapidamente? Eu tenho uma matriz chamada múltiplos e gostaria de saber a soma dos múltiplos.

Respostas:


466

Este é o método mais fácil / mais curto que posso encontrar.

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: +)

Mais algumas informações:

Isso usa o método de redução da matriz (documentação aqui ), que permite "reduzir uma coleção de elementos para um único valor aplicando recursivamente o fechamento fornecido". Damos 0 como o valor inicial e, em seguida, essencialmente, o fechamento { $0 + $1 }. Obviamente, podemos simplificar isso para um único sinal de mais, porque é assim que o Swift rola.


42
Obrigado por esta resposta. Ele funciona muito bem e eu só quero acrescentar o meu código de exemplo, com variedade de classes personalizadas:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal

2
Ótima resposta, mas falta o nome do parâmetro combine. Deveria ser multiples.reduce(0, combine: +).
Evgenii

2
É mais rápido que um loop for?
Lorenzo

1
@SwiftMatt Tente usar um flatMapprimeiro para achatá-lo em uma matriz de dimensão única. multiArray.flatMap{$0}.reduce(0, combine: +)
Samah

2
@lorenzo - Testar em um iPhone 7 com o Swift e o XCode mais recentes (uma matriz simples preenchida com 1.000.000 valores aleatórios do UInt32 limitados a 256 para evitar o estouro do UInt32) mostra de maneira interessante que o loop 'for' é apenas um pouco mais rápido (1,941 segundos versus 2,137 segundos) , embora essa vantagem não esteja presente em 100.000 valores (0,23 segundos cada). IMHO, a clareza do código vale qualquer custo de desempenho muito menor aqui, mesmo ao lidar com matrizes de 32 MB.
Tom Dibble

84

Swift 3+ um liner para somar propriedades dos objetos

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

Onde points é a propriedade em meu objeto personalizado scaleData que estou tentando reduzir



22

No Swift 4, você também pode restringir os elementos da sequência ao protocolo numérico para retornar a soma de todos os elementos na sequência, conforme a seguir

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

editar / atualizar:

Xcode 10.2 • Swift 5 ou posterior

Podemos simplesmente restringir os elementos da sequência ao novo protocolo AdditiveArithmetic para retornar a soma de todos os elementos na coleção

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

Xcode 11 • Swift 5.1 ou posterior

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
Ótima, ótima solução!
sabiland 23/08/19

11

Isso também funciona:

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

O resultado será: 55


10

Exemplo do 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

Swift 3

Se você possui uma matriz de objetos genéricos e deseja somar alguma propriedade do objeto, então:

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 

Apesar da forma mais curta, muitas vezes você pode preferir o ciclo for-clássico:

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, aqui está a minha solução: array.map ({$ 0.value}) reduzir (0, +).
Ivailo Kanev

Dessa forma, você escreve mais código e incrementa a complexidade. Então, por que?
Luca Davanzo

6

Que tal a maneira simples de

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

// onde n = número de elementos na matriz


Observe que no Swift 3 isso não é mais válido porque o estilo C para loops foi removido do idioma. Em vez disso, use loops de entrada, o Swift acompanha internamente o índice.
Donarb

1
Isso não funcionaria como isso. Você precisa inicializar a soma para 0 primeiro. A beleza de reduzir é que você lembra o valor inicial.
Mark3urelius #

var sum = 0 ; for n in multiples { sum += n }embora eu usaria reduzir.
precisa saber é o seguinte

2

Uma solução possível: defina um operador de prefixo para ele. Como o operador de redução "+ /" como no APL (por exemplo, GNU APL)

Um pouco de uma abordagem diferente aqui.

O uso de um protocolo em um tipo genérico nos permite usar esse operador nos tipos de matriz 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
   }
}

use assim:

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

(atualizado para Swift 2.2, testado no Xcode versão 7.3)


Um problema é que muitas vezes (pelo menos ao lidar com matrizes grandes) você precisará que a soma seja de um tipo diferente dos componentes. Por exemplo, se você tiver um milhão de UInt32s executando a gama de 0 a 2 ^ 32-1 (por exemplo, preenchido por arc4random ()), adicionar esses valores excederá seu valor de "soma" do UInt32 toda vez.
Tom Dibble

2

Swift 3.0

eu tive o mesmo problema, encontrei na documentação Apple esta solução.

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

Mas, no meu caso, eu tinha uma lista de objetos, então eu precisava transformar meu valor da minha lista:

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

este trabalho para mim.


0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

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

usou este para parâmetros aninhados


0

Mantenha simples...

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

Resultado:

Minha soma dos elementos é: 37


0

Para mim, era assim usando propriedade

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

-2

Swift 3

De todas as opções exibidas aqui, essa é a que funcionou para mim.

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


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

Esta é apenas uma cópia de outra resposta #
Ashley Mills

-2

Para soma dos elementos na matriz de objetos

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

-4

esta é a minha abordagem sobre isso. no entanto, acredito que a melhor solução é a resposta do nome de usuário do usuário tbd

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.