在Swift数组中查找元素的总和


228

快速找到整数数组总和的最简单(最佳)方法是什么?我有一个称为倍数的数组,我想知道倍数的总和。

Answers:


465

这是我能找到的最简单/最短的方法。

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的reduce方法(在此处提供文档),该方法允许您“通过递归应用提供的闭包将元素的集合减少到单个值”。我们给它0作为初始值,然后本质上给闭包赋值{ $0 + $1 }。当然,我们可以将其简化为单个加号,因为这就是Swift的滚动方式。


42
感谢您的回答。它很好用,我只想添加带有自定义类数组的示例代码:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
Libor Zapletal 2015年

2
好的答案,但缺少参数名称combine。应该是multiples.reduce(0, combine: +)
Evgenii

2
它比for循环快吗?
洛伦佐

1
@SwiftMatt首先尝试flatMap在其上将其展平为一个单一维度的数组。multiArray.flatMap{$0}.reduce(0, combine: +)
萨玛

2
@lorenzo-在具有最新Swift和XCode(填充有1,000,000个UInt32随机值的简单数组,上限为256,以防止UInt32溢出)的iPhone 7上进行的测试有趣地显示,“ for”循环的速度更快(1.941秒对2.137秒) ,尽管该优势在100,000个值(每个0.23秒)时存在。恕我直言,即使在处理32MB阵列时,代码清晰度也不值得付出任何很小的性能成本。
汤姆·迪布尔

83

Swift 3+一线可叠加对象的属性

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

其中是我的自定义对象的属性scaleData,我试图减少


28

Swift3已更改为:

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

22

Swift 4中,您还可以将序列元素约束为数字协议,以返回序列中所有元素的总和,如下所示

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 

尽管格式较短,但很多时候您可能更喜欢经典的for周期:

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.value})。reduce(0,+)
Ivailo Kanev

这样,您可以编写更多代码并增加复杂度。.为什么呢?
卡·达万佐

6

简单的方法怎么样

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

// n =数组中的元素数


请注意,在Swift 3中,这不再有效,因为已从该语言中删除了C样式的循环。相反,使用for-in循环,Swift会在索引内部进行跟踪。
donarb

1
那是行不通的。您必须先将总和初始化为0。减少的好处在于,它使您想起初始值。
MarkAurelius

var sum = 0 ; for n in multiples { sum += n }虽然我会使用减少。
JeremyP'3

2

一种可能的解决方案:为其定义前缀运算符。就像APL(例如GNU APL)中的reduce“ + /”运算符一样

这里有点不同的方法。

使用协议en泛型类型使我们可以在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的“ sum”值。
汤姆·迪布尔

2

斯威夫特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

把事情简单化...

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



-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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.