【问题标题】:Finding sum of elements in Swift array在 Swift 数组中查找元素的总和
【发布时间】:2014-09-07 19:52:51
【问题描述】:

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

【问题讨论】:

    标签: arrays swift


    【解决方案1】:

    另一种简单的方法:

    let sumOfMultiples = ar.reduce(0) { x, y in x + y }          
    print(sumOfMultiples)
    

    【讨论】:

      【解决方案2】:

      Swift 3、4 和 5

      使用减少:

      let totalAmount = yourTransactionsModelArray.reduce(0) { $0 + $1.amount}

      用于理解目的的老式方法:

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

      //其中 n = 数组中的元素个数

      【讨论】:

      • 请注意,在 Swift 3 中这不再有效,因为 C 风格的 for 循环已从语言中删除。改用 for-in 循环,Swift 在内部跟踪索引。
      • 那行不通。您必须先将 sum 初始化为 0。 reduce 的美妙之处在于它提醒您考虑初始值。
      • var sum = 0 ; for n in multiples { sum += n } 虽然我会使用 reduce。
      【解决方案3】:

      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
      

      要对自定义对象的属性求和,我们可以扩展 Sequence 以采用谓词返回符合 AdditiveArithmetic 的值:

      extension Sequence  {
          func sum<T: AdditiveArithmetic>(_ predicate: (Element) -> T) -> T { reduce(.zero) { $0 + predicate($1) } }
      }
      

      用法:

      struct Product {
          let id: String
          let price: Decimal
      }
      
      let products: [Product] = [.init(id: "abc", price: 21.9),
                                 .init(id: "xyz", price: 19.7),
                                 .init(id: "jkl", price: 2.9)
      ]
      
      products.sum(\.price)  // 44.5
      

      【讨论】:

      • 很好,很好的解决方案!
      【解决方案4】:

      对我来说,使用属性是这样的

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

      【讨论】:

        【解决方案5】:

        Swift 3+ 一种对对象的属性求和的衬垫

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

        points 是我想要减少的自定义对象 scaleData 中的属性

        【讨论】:

        • 这将不必要地迭代整个集合两次
        • 你可以通过scaleData.reduce(0) { $0 + $1.points }实现这一点
        【解决方案6】:

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

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

        【讨论】:

        • 感谢您的回答。它工作得很好,我只想添加我的示例代码和自定义类数组:let totalSum = self.cheques.reduce(0) { $0 + $1.amount}
        • 很好的答案,但缺少参数名称combine。应该是multiples.reduce(0, combine: +)
        • 它比 for 循环快吗?
        • @SwiftMatt 首先尝试在其上使用flatMap 将其展平为一维数组。 multiArray.flatMap{$0}.reduce(0, combine: +)
        • @lorenzo - 在 iPhone 7 上使用最新的 Swift 和 XCode 进行测试(一个包含 1,000,000 个 UInt32 随机值的简单数组,上限为 256,以防止 UInt32 溢出)有趣地显示了“for”循环只是一根头发更快(1.941 秒对 2.137 秒),尽管在 100,000 个值(每个 0.23 秒)时存在这种优势。恕我直言,即使在处理 32MB 数组时,代码清晰度也值得任何非常小的性能成本。
        【解决方案7】:

        对象数组中元素的总和

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

        【讨论】:

          【解决方案8】:

          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】:

          保持简单...

          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

          【讨论】:

            【解决方案10】:

            斯威夫特 3

            从此处显示的所有选项中,这是对我有用的选项。

            let arr = [6,1,2,3,4,10,11]
            
            
            var sumedArr = arr.reduce(0, { ($0 + $1)})
            print(sumedArr)
            

            【讨论】:

            • 这只是另一个答案的副本
            【解决方案11】:

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

            【讨论】:

            • ciao Luca,这是我的解决方案:array.map({$0.value}).reduce(0, +)
            • 这样你写了更多的代码并增加了复杂性。那么,为什么?
            【解决方案12】:
            @IBOutlet var valueSource: [MultipleIntBoundSource]!
            
            private var allFieldsCount: Int {
                var sum = 0
                valueSource.forEach { sum += $0.count }
                return sum
            }
            

            将这个用于嵌套参数

            【讨论】:

              【解决方案13】:

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

              这对我有用。

              【讨论】:

                【解决方案14】:

                这也有效:

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

                结果将是:55

                【讨论】:

                  【解决方案15】:

                  Swift3 已更改为:

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

                  【讨论】:

                    【解决方案16】:

                    一个可能的解决方案:为它定义一个前缀运算符。 就像 APL 中的 reduce "+/" 运算符(例如 GNU APL)

                    这里有点不同的方法。

                    使用协议和泛型类型允许我们在 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“总和”值。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-10-14
                    • 1970-01-01
                    • 2022-01-09
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多