我在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({...})
}
我的数据输入为:
一旦我循环,我想返回一个新数组:
基于输入的预期结果:
我写了很多行代码而且发布它太混乱了。我找到了更简单的方法,有人对此有所了解吗?
答案 0 :(得分:2)
首先,您不应该为您的班级Data
命名,因为这是基础班级的名称。我使用了一个名为MyData
的结构代替:
struct MyData {
let value: CGFloat
let name: String
}
let myArray: [MyData] = [MyData(value: 10.5, name: "apple"),
MyData(value: 20.0, name: "lemon"),
MyData(value: 15.2, name: "apple"),
MyData(value: 45, name: "")]
您可以使用字典来添加与每个名称关联的值:
var myDictionary = [String: CGFloat]()
for dataItem in myArray {
if dataItem.name.isEmpty {
// ignore entries with empty names
continue
} else if let currentValue = myDictionary[dataItem.name] {
// we have seen this name before, add to its value
myDictionary[dataItem.name] = currentValue + dataItem.value
} else {
// we haven't seen this name, add it to the dictionary
myDictionary[dataItem.name] = dataItem.value
}
}
然后你可以将字典转换回MyData
个对象的数组,对它们进行排序并打印出来:
// turn the dictionary back into an array
var resultArray = myDictionary.map { MyData(value: $1, name: $0) }
// sort the array by value
resultArray.sort { $0.value < $1.value }
// print the sorted array
for dataItem in resultArray {
print("\(dataItem.value) \(dataItem.name)")
}
答案 1 :(得分:2)
首先在Swift 3中保留Data
,该示例使用名为Item
的 struct 。
struct Item {
let value : Float
let name : String
}
使用您给定的值
创建数据数组let dataArray = [Item(value:10.5, name:"apple"),
Item(value:20.0, name:"lemon"),
Item(value:15.2, name:"apple"),
Item(value:45, name:"")]
以及结果数组:
var resultArray = [Item]()
现在过滤所有非空的名称并生成Set
- 每个名称在集合中出现一次:
let allKeys = Set<String>(dataArray.filter({!$0.name.isEmpty}).map{$0.name})
通过密钥迭代,使用相同名称过滤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))
}
最后按值desscending对结果数组进行排序:
resultArray.sorted(by: {$0.value < $1.value})
答案 2 :(得分:0)
首先更改数据类,使字符串成为可选字符串,它变得更容易处理。所以现在如果没有名字,那就是零。如果您需要稍微改变一下,可以将其保留为“”。
class Thing {
let name: String?
let value: Double
init(name: String?, value: Double){
self.name = name
self.value = value
}
static func + (lhs: Thing, rhs: Thing) -> Thing? {
if rhs.name != lhs.name {
return nil
} else {
return Thing(name: lhs.name, value: lhs.value + rhs.value)
}
}
}
我给了它一个操作员,因此可以轻松添加它们。它返回一个可选项,因此在使用时要小心。
然后让我们为充满东西的数组做一个方便的扩展:
extension Array where Element: Thing {
func grouped() -> [Thing] {
var things = [String: Thing]()
for i in self {
if let name = i.name {
things[name] = (things[name] ?? Thing(name: name, value: 0)) + i
}
}
return things.map{$0.1}.sorted{$0.value > $1.value}
}
}
快速测试一下:
let t1 = Thing(name: "a", value: 1)
let t2 = Thing(name: "b", value: 2)
let t3 = Thing(name: "a", value: 1)
let t4 = Thing(name: "c", value: 3)
let t5 = Thing(name: "b", value: 2)
let t6 = Thing(name: nil, value: 10)
let bb = [t1,t2,t3,t4,t5,t6]
let c = bb.grouped()
//(“b”,4),(“c”,3),(“a”,2)
编辑:添加了一个名为nil的示例,该示例由groups()函数中的if let过滤掉