Encontrar la suma de elementos en la matriz Swift

229

¿Cuál es la forma más fácil (mejor) de encontrar la suma de una matriz de enteros en Swift? Tengo una matriz llamada múltiplos y me gustaría saber la suma de los múltiplos.

ejLev
fuente

Respuestas:

466

Este es el método más fácil / más corto que puedo encontrar.

Swift 3 y Swift 4:

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

Swift 2:

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

Alguna información más:

Utiliza el método de reducción de Array (documentación aquí ), que le permite "reducir una colección de elementos a un solo valor aplicando recursivamente el cierre proporcionado". Le damos 0 como valor inicial, y luego, esencialmente, el cierre { $0 + $1 }. Por supuesto, podemos simplificar eso a un solo signo más, porque así es como funciona Swift.

nombre de usuario tbd
fuente
42
Gracias por esta respuesta Funciona muy bien y solo quiero agregar mi código de ejemplo con una variedad de clases personalizadas:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal
2
Gran respuesta pero falta el nombre del parámetro combine. Debe ser multiples.reduce(0, combine: +).
Evgenii
2
¿Es más rápido que un bucle for?
lorenzo
1
@SwiftMatt Intente usar un flatMapen él primero para aplanarlo a una matriz de una sola dimensión. multiArray.flatMap{$0}.reduce(0, combine: +)
Samah
2
@lorenzo: las pruebas en un iPhone 7 con el último Swift y XCode (una matriz simple llena de 1,000,000 de valores aleatorios UInt32 con un límite de 256 para evitar el desbordamiento de UInt32) muestran de manera interesante que el bucle 'for' es solo un pelo más rápido (1.941 segundos frente a 2.137 segundos) , aunque esa ventaja no está presente en 100,000 valores (0.23 segundos cada uno). En mi humilde opinión, la claridad del código vale cualquier costo de rendimiento muy pequeño aquí incluso cuando se trata de matrices de 32 MB.
Tom Dibble
85

Swift 3+ un revestimiento para sumar propiedades de objetos

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

Donde puntos es la propiedad en mi objeto personalizado scaleData que estoy tratando de reducir

Jesus Rodriguez
fuente
28

Swift3 ha cambiado a:

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

En Swift 4 también puede restringir los elementos de secuencia al protocolo numérico para devolver la suma de todos los elementos de la secuencia de la siguiente manera

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

editar / actualizar:

Xcode 10.2 • Swift 5 o posterior

Simplemente podemos restringir los elementos de secuencia al nuevo protocolo AdditiveArithmetic para devolver la suma de todos los elementos de la colección.

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

Xcode 11 • Swift 5.1 o 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
Leo Dabus
fuente
1
Genial, buena solución!
sabiland
11

Esto también funciona:

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

El resultado será: 55

Marco Almeida
fuente
10

Swift 4 ejemplo

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
Maciej
fuente
9

Swift 3

Si tiene una matriz de objetos genéricos y desea sumar alguna propiedad del objeto, entonces:

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 

A pesar de la forma más corta, muchas veces puede preferir el ciclo clásico:

let array = [A(value: 2), A(value: 4)]
var sum = 0
array.forEach({ sum += $0.value}) 
// or
for element in array {
   sum += element.value
}
Luca Davanzo
fuente
1
chao Luca, aquí está mi solución: array.map ({$ 0.value}). reduce (0, +)
Ivailo Kanev
De esta manera, escribe más código e incrementa la complejidad ... entonces, ¿por qué?
Luca Davanzo
6

¿Qué tal la forma simple de

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

// donde n = número de elementos en la matriz

Naishta
fuente
Tenga en cuenta que en Swift 3 esto ya no es válido porque el estilo C para los bucles se ha eliminado del lenguaje. En su lugar, use bucles for-in, Swift realiza un seguimiento interno del índice.
donarb
1
Eso no funcionaría así. Primero debe inicializar la suma a 0. La belleza de reducir es que te recuerda pensar en el valor inicial.
MarkAurelius
var sum = 0 ; for n in multiples { sum += n }aunque usaría reduce.
JeremyP
2

Una posible solución: definir un operador de prefijo para él. Como el operador de reducción "+ /" como en APL (por ejemplo, GNU APL)

Un enfoque un poco diferente aquí.

El uso de un protocolo en tipo genérico nos permite usar este operador en los tipos de matriz Doble, Flotante 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
   }
}

usar así:

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

(actualizado para Swift 2.2, probado en Xcode versión 7.3)

Ted van Gaalen
fuente
Un problema con esto es que a menudo (al menos, cuando se trata de matrices grandes) necesitará que la suma sea de un tipo diferente que los componentes. Por ejemplo, si tiene un millón de UInt32s que ejecutan la gama de 0 a 2 ^ 32-1 (por ejemplo, poblada por arc4random ()), sumarlos desbordará su valor de "suma" UInt32 cada vez.
Tom Dibble
2

Swift 3.0

Tuve el mismo problema, encontré en la documentación de Apple esta solución.

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

Pero, en mi caso, tenía una lista de objetos, luego necesitaba transformar el valor de mi lista:

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

este trabajo para mi

Luan Almeida
fuente
0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

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

usado este para parámetros anidados

Alexey Lysenko
fuente
0

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

Salida:

Mi suma de elementos es: 37

Israel Manzo
fuente
0

Para mí, fue así usando la propiedad

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

Swift 3

De todas las opciones que se muestran aquí, esta es la que funcionó para mí.

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


var sumedArr = arr.reduce(0, { ($0 + $1)})
print(sumedArr)
Víctor
fuente
Esta es solo una copia de otra respuesta
Ashley Mills,
-2

Para la suma de elementos en una matriz de objetos

self.rankDataModelArray.flatMap{$0.count}.reduce(0, +)
Manish Mahajan
fuente
-4

Este es mi enfoque sobre esto. Sin embargo, creo que la mejor solución es la respuesta del nombre de usuario tbd

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
usuario3413044
fuente