Ios Swift 3:对象数组的group by和值

Ios Swift 3:对象数组的group by和值,ios,arrays,swift,Ios,Arrays,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({...}) } var myArray:Array=Array() 对于我在0

我的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({...})
}
var myArray:Array=Array()

对于我在0….. P>首先,你不应该说出你的类<代码>数据< /代码>,因为这是一个基础类的名字。我使用了一个名为
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)")
}
//将字典转换回数组
var resultArray=myDictionary.map{MyData(值:$1,名称:$0)}
//按值对数组排序
resultArray.sort{$0.value<$1.value}
//打印已排序的数组
对于resultArray中的dataItem{
打印(“\(dataItem.value)\(dataItem.name)”)
}

首先,Swift 3中保留了
数据
,示例使用名为
项的结构

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]()
现在筛选所有非空名称,并设置一个
集合
-每个名称在集合中出现一次:

let allKeys = Set<String>(dataArray.filter({!$0.name.isEmpty}).map{$0.name})
最后,按值desscending对结果数组进行排序:

resultArray.sorted(by: {$0.value < $1.value})

首先更改您的数据类,使字符串成为可选的,这样就更容易处理了。所以现在如果没有名字,它是零。如果需要,您可以将其保留为“”,只需在下面稍作更改:

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的示例,该示例由If让在GROUPER()函数中筛选出来,考虑重新命名数据类,因为基金会包含一个按该名称命名的类。请向我们展示迄今为止您的最佳解决方案,我们可以让您知道您在哪里出错,我正在玩您的答案来理解。我编写了
letallkeys=Set(dataArray.filter({!$0.name.isEmpty}))
。我故意没有编写
映射{$0.name})
来查看/理解我得到了什么…但是我得到了一个错误,说ambigous reference to member filter。我看了看,但还是解决不了。我做错了什么?没有
map
你就得到
Set
我得到了。但是现在,如果我只在你的答案中写那么远的话,为什么会出现这样的错误呢?
集合
中使用的类型必须符合
哈希表
,而简单结构没有。这个错误可能会误导你。歧义是类型不匹配–
Set
被注释,但推断的类型是
Set
,或者无法创建集,因为
不可散列。显然,这是可行的,但它是以非常不快速的方式编写的。:)
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()