Swift 3:通过对象数组的分组求和值

Zig*_*ggy 2 arrays ios swift

我的 viewController 中有这段代码

var myArray :Array<Data> = Array<Data>()
for i in 0..<mov.count {    
   myArray.append(Data(...))
}

class Data {
    var value :CGFloat
    var name  :String=""
    init({...})
}
Run Code Online (Sandbox Code Playgroud)

我输入的数据如下:

  • 10.5个苹果
  • 20.0 柠檬
  • 15.2 苹果
  • 45

一旦我循环,我想返回一个新数组:

  • sum(值) 按名称分组
  • 删除最后一行,因为没有名字
  • 按值排序

基于输入的预期结果:

  • 25.7 苹果
  • 20.0 柠檬
  • 没有别的

我写了很多行代码,太混乱了,无法发布。我会找到更简单的方法,有人对此有想法吗?

vad*_*ian 5

首先Data是 Swift 3 中保留的,该示例使用名为 的结构体Item

struct Item {
    let value : Float
    let name  : String
}
Run Code Online (Sandbox Code Playgroud)

使用给定值创建数据数组

let dataArray = [Item(value:10.5, name:"apple"), 
                 Item(value:20.0, name:"lemon"), 
                 Item(value:15.2, name:"apple"), 
                 Item(value:45, name:"")]
Run Code Online (Sandbox Code Playgroud)

以及结果的数组:

var resultArray = [Item]()
Run Code Online (Sandbox Code Playgroud)

现在过滤所有不为空的名称并创建一个Set- 每个名称在集合中出现一次:

let allKeys = Set<String>(dataArray.filter({!$0.name.isEmpty}).map{$0.name})
Run Code Online (Sandbox Code Playgroud)

遍历键,过滤所有具有dataArray相同名称的项目,对值求和并创建一个Item具有总价值的新项目:

for key in allKeys {
    let sum = dataArray.filter({$0.name == key}).map({$0.value}).reduce(0, +)
    resultArray.append(Item(value:sum, name:key))
}
Run Code Online (Sandbox Code Playgroud)

最后按值降序对结果数组进行排序:

resultArray.sorted(by: {$0.value < $1.value})
Run Code Online (Sandbox Code Playgroud)

---

编辑:

Swift 4 中引入了一个更有效的 API,可以通过谓词对数组进行分组,Dictionary(grouping:by:

var grouped = Dictionary(grouping: dataArray, by:{$0.name})
grouped.removeValue(forKey: "") // remove the items with the empty name

resultArray = grouped.keys.map { (key) -> Item in
    let value = grouped[key]!
    return Item(value: value.map{$0.value}.reduce(0.0, +), name: key)
}.sorted{$0.value < $1.value}

print(resultArray)
Run Code Online (Sandbox Code Playgroud)