Пошук суми елементів у масиві Swift


228

Який найпростіший (найкращий) спосіб швидко знайти суму цілих чисел? У мене є масив під назвою кратних, і я хотів би знати суму кратних.

Відповіді:


466

Це найпростіший / найкоротший метод, який я можу знайти.

Swift 3 та Swift 4:

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

Швидкий 2:

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

Ще трохи інформації:

Для цього використовується метод зменшення Array ( тут документація ), який дозволяє "зменшити набір елементів до одного значення шляхом рекурсивного застосування передбаченого закриття". Ми даємо це 0 як початкове значення, а потім, по суті, закриття { $0 + $1 }. Звичайно, ми можемо спростити це до одного знака плюс, тому що саме так Свіфт перекидається.


42
Дякую за цю відповідь. Це чудово працює, і я просто хочу додати свій приклад код з масивом користувацьких класів:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal

2
Відмінна відповідь, але відсутні параметр combine. Повинно бути multiples.reduce(0, combine: +).
Євгеній

2
Це швидше, ніж для циклу?
lorenzo

1
@SwiftMatt Спробуйте спочатку скористатися символом a, flatMapщоб вирівняти його в масив одного виміру. multiArray.flatMap{$0}.reduce(0, combine: +)
Сама

2
@lorenzo - Тестування на iPhone 7 з останніми Swift та XCode (простий масив, наповнений 1 000 000 випадкових значень UInt32, обмежених 256, щоб запобігти переповненню UInt32), що цікаво показує, що цикл "для" швидше просто волосся (1.941 секунди проти 2.137 секунд) , хоча ця перевага полягає в тому, НЕ присутній на 100000 значень (0,23 секунд кожен). IMHO, чіткість коду вартує будь-яких дуже незначних витрат на продуктивність, навіть при роботі з масивами 32 Мб.
Том Діббл

84

Перемістіть 3+ один вкладиш, щоб підсумовувати властивості об'єктів

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

Де точки - це властивість у моєму користувальницькому масштабі об’єктів Дані, які я намагаюся зменшити



22

У Swift 4 ви також можете обмежити елементи послідовності протоколом Numeric , щоб повернути суму всіх елементів у послідовності, як описано нижче

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

редагування / оновлення:

Xcode 10.2 • Swift 5 або новішої версії

Ми можемо просто обмежити елементи послідовності новим протоколом AdditiveArithmetic , щоб повернути суму всіх елементів колекції

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

Xcode 11 • Swift 5.1 або новішої версії

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
Чудове, приємне рішення!
sabiland


10

Приклад 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

Швидкий 3

Якщо у вас є масив загальних об'єктів і ви хочете підсумувати деяку властивість об'єкта, виконайте наступні дії:

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 

Незважаючи на більш коротку форму, ви багато разів можете віддати перевагу класичному для циклу:

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, ось моє рішення: array.map ({$ 0.значення}). зменшити (0, +)
Івайло Канев

Таким чином ви пишете більше складності коду та приросту .. так, чому?
Лука Даванцо

6

Як щодо простого способу

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

// де n = кількість елементів у масиві


Зауважте, що в Swift 3 це більше не діє, оскільки стиль C для циклів видалено з мови. Замість цього використовуйте петлі для входу, Swift внутрішньо відстежує індекс.
донарб

1
Це не працювало б так. Спершу ви повинні ініціалізувати суму до 0. Краса зменшення полягає в тому, що вона нагадує вам думати про початкову цінність.
МаркАврелій

var sum = 0 ; for n in multiples { sum += n }хоча я б скористався скороченням.
JeremyP

2

Можливе рішення: визначте для нього оператор префікса. Як оператор скорочення "+ /", як у APL (наприклад, GNU APL)

Тут трохи інший підхід.

Використання протоколу en generic типу дозволяє використовувати цей оператор для типів масивів Double, Float та 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
   }
}

використовувати так:

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, тестується у версії Xcode 7.3)


Одне питання з цим полягає в тому, що часто (принаймні, при роботі з великими масивами) вам знадобиться, щоб сума була іншим типом, ніж компоненти. Наприклад, якщо у вас є мільйон UInt32, які працюють із діапазоном від 0 до 2 ^ 32-1 (наприклад, заселене arc4random ()), додавання цих даних щоразу переповнює ваше значення UInt32 "сума".
Том Діббл

2

Swift 3.0

У мене була така ж проблема, я знайшов у документації Apple це рішення.

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

Але, у моєму випадку у мене був список об’єктів, тоді мені потрібно було перетворити значення мого списку:

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

ця робота для мене.


0
@IBOutlet var valueSource: [MultipleIntBoundSource]!

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

використовував цей для вкладених параметрів


0

Не ускладнювати...

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

Вихід:

Моя сума елементів: 37


0

Для мене це було так, використовуючи властивість

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

-2

Швидкий 3

З усіх опцій, що відображаються тут, це той, який працював для мене.

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


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

Це лише копія іншої відповіді
Ешлі Міллс


-4

це мій підхід з цього приводу. однак я вважаю, що найкращим рішенням є відповідь від імені користувача tbd

var i = 0 
var sum = 0
let example = 0
for elements in multiples{
    i = i + 1
    sum = multiples[ (i- 1)]
    example = sum + example
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.