包含自定义类的数组总和(Swift)

Posted

技术标签:

【中文标题】包含自定义类的数组总和(Swift)【英文标题】:Sum of Array containing custom class (Swift) 【发布时间】:2019-07-09 20:44:49 【问题描述】:

我正在寻找一种方法来获取包含在数组中的类的值的总和。我的设置如下:

class CustomClass 
    var value: Int?
    init(value: Int) 
       self.value = value
    


let object1 = CustomClass(value: 2)
let object2 = CustomClass(value: 4)
let object3 = CustomClass(value: 8)

let array: [CustomClass] = [object1, object2, object3]

我目前的解决方案如下:

var sumArray = [Int]()
for object in array 
    sumArray.append(object.value!)

let sum = sumArray.reduce(0, +)

问题在于,对于具有许多其他值的类,它变得非常复杂,有人知道更好的解决方案吗?

【问题讨论】:

当您说“非常复杂的类具有许多其他值”时,这是否意味着您也在尝试将不同类型的类的值包含到求和运算中? 是的,确实如此。事实上,我的课程包含 Int 和 Date 类型,但日期类型不应该被“合并”.. @AndreasSchultz 到目前为止,我没有看到任何复杂的东西。您必须以某种方式将对象转换为数字(您已经在这样做了,尽管 .map 会是更好的解决方案),然后将数字相加。 【参考方案1】:

您可以将您的自定义类数组压缩映射为整数数组,然后将该数组缩减为其总和。喜欢,

let sum = array.lazy.compactMap  $0.value 
            .reduce(0, +)

【讨论】:

使用尾随闭包,可以简化为.reduce(0, +) 我会在那里放一个lazy,以跳过compactMap导致的中间数组分配 @Alexander 我想知道该怎么做。是不是像lazy var sum = array.compactMap $0.value .reduce(0, +) ?? 不不,lazy 属性使表达式在第一次请求时计算。它仍然涉及中间数组。相反,您使用数组的 lazy 计算属性,它返回一个惰性视图,该视图跟踪您要执行的操作,在需要结果之前不实际执行它们。 array.lazy.compactMap $0.value .reduce(0, +)【参考方案2】:

您可以在array 上使用单个reduce

let sumOfValues = array.reduce($0 += ($1.value ?? 0))

【讨论】:

没有必要为此使用reduce into。 reduce(0) $0 + ($1.value ?? 0) @LeoDabus 你是对的,没有需要使用reduce(into:,_:),但我也没有看到使用reduce(_:,_:) 的任何优势 有但我不适合向您解释。在 Swift 4 中实现 reduce(into:) 之前,人们有时需要将结果声明为变量,以便能够在闭包内对其进行更改。如果您不需要更改它,只需使用简单的 reduce 并返回总和 result 加上元素。 Resuming 如果你使用普通的 reduce 方法,闭包内没有变量,只有常量【参考方案3】:

我将为您的类或结构创建一个包含值的协议。并将其声明更改为非可选。

protocol Valueable 
    var value: Int  get 

那么你需要让你的类符合那个协议:

class CustomClass: Valueable 
    let value: Int
    init(value: Int) 
        self.value = value
    

现在您可以使用只读实例属性扩展收集协议,以返回数组中所有元素的总和。

extension Collection where Element: Valueable 
    var sum: Int 
        return reduce(0)  $0 + $1.value 
    
 

let object1 = CustomClass(value: 2)
let object2 = CustomClass(value: 4)
let object3 = CustomClass(value: 8)

let objects = [object1, object2, object3]

let sum = objects.sum   // 14

编辑/更新:

另一种选择是扩展序列并添加一个generic sum method,它接受其属性符合AdditiveArithmetic的关键路径


或将关联类型添加到符合 AdditiveArithmetic 的协议中:

protocol Valueable 
    associatedtype Value: AdditiveArithmetic
    var value: Value  get 


extension Collection where Element: Valueable 
    var sum: Element.Value  reduce(.zero)  $0 + $1.value  


class CustomClass: Valueable 
    let value: Decimal
    init(value: Decimal) 
        self.value = value
    


用法:

let object1 = CustomClass(value: 123.4567)
let object2 = CustomClass(value: 12.34567)
let object3 = CustomClass(value: 1.234567)

let objects = [object1, object2, object3]

let sum = objects.sum   // 137.036937

【讨论】:

这太复杂了,抱歉。 @user3069232 这取决于你的编程水平。这是非常基本的协议用法,这是 Swift 成功的主要原因(面向协议的语言) @user3069232 另一种选择是扩展序列并添加一个generic sum method,它接受其属性符合AdditiveArithmetic的关键路径 @user3069232 检查我上次的编辑。那是它开始变得复杂的时候。

以上是关于包含自定义类的数组总和(Swift)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 3 中将具有自定义类的数组转换为 JSON

来自自定义类的 Swift addChild

对包含自定义类的列表进行排序

java创建自定义类的数组

Swift:确定自定义对象数组是不是包含特定字符串[重复]

在 Swift 中的视图控制器之间传递自定义类数据