如何加速对由两个属性分组的结构数组求和-macOS Swift

如何加速对由两个属性分组的结构数组求和-macOS Swift,swift,Swift,我正在使用的代码如下所示,但计算和似乎非常慢-大约20秒。关于如何加快这一进程,有什么建议吗 实际上这有点复杂,因为我需要创建一个精细的结果对象,其中包含所有原始属性和更新为总和的计数 struct PAData: Equatable, Hashable { let pCode: String let aCode: String let otherProperty1: String // Unique to pCode let ot

我正在使用的代码如下所示,但计算和似乎非常慢-大约20秒。关于如何加快这一进程,有什么建议吗

实际上这有点复杂,因为我需要创建一个精细的结果对象,其中包含所有原始属性和更新为总和的计数

struct PAData: Equatable, Hashable {
        let pCode: String
        let aCode: String
        let otherProperty1: String // Unique to pCode
        let otherProperty2: String // Unique to pCode
        let count: Int
        
        static func == (lhs: PAData, rhs: PAData) -> Bool {
                return
                    lhs.pCode == rhs.pCode &&
                    lhs.aCode == rhs.aCode
            }
        func hash(into hasher: inout Hasher) {
                hasher.combine(pCode)
                hasher.combine(aCode)
            }
}

// Group by aCode and pCode and sum count
func calcSum() {
    // Find the unique records based on pCode/aCode properties - very fast takes 0.1 second
    let unique = Set<PAData>(paData)

    // Now find the sum for each pCode/aCode group  - too slow takes 20 seconds to complete - how to speed this up ?
    // Really only needs to be done for those that have more than one record !??
    for key in unique {
                
        let sum = paData.filter({$0.pCode == key.pCode && $0.aCode == key.aCode}).map({$0.count}).reduce(0, +)

        let summary = PAData(pCode: key.pCode, aCode: key.aCode, count: sum)

        resultArray.append(summary)
    }
}
struct PAData:equalable,Hashable{
让pCode:String
让代码:字符串
让otherProperty1:String//对pCode唯一
让otherProperty2:String//对pCode唯一
计数:Int
静态函数==(左:PAData,右:PAData)->Bool{
返回
lhs.pCode==rhs.pCode&&
lhs.aCode==rhs.aCode
}
func散列(放入散列程序:inout散列程序){
hasher.combine(pCode)
联合收割机(aCode)
}
}
//按aCode、pCode和总和计数分组
func calcSum(){
//根据pCode/aCode属性查找唯一记录-非常快需要0.1秒
let unique=Set(paData)
//现在找到每个pCode/aCode组的总和-太慢需要20秒才能完成-如何加快速度?
//真的只需要为那些有一个以上记录的人做!??
用于输入唯一的{
让sum=paData.filter({$0.pCode==key.pCode&&$0.aCode==key.aCode}).map({$0.count}).reduce(0,+)
let summary=PAData(pCode:key.pCode,aCode:key.aCode,count:sum)
resultArray.append(摘要)
}
}
使用Dictionary.grouping()似乎很快,但是合并结果又很慢,仍然需要大约35秒

struct PAData: Equatable, Hashable {
    let pCode: String
    let aCode: String
    let count: Int

    var key: String {
        return pCode + ":" + aCode
    }
    
    static func == (lhs: PAData, rhs: PAData) -> Bool {
            return
                lhs.pCode == rhs.pCode &&
                lhs.aCode == rhs.aCode
        }
    func hash(into hasher: inout Hasher) {
            hasher.combine(pCode)
            hasher.combine(aCode)
        }
}

    // Group by aCode and pCode and sum count
    func calcSum() {
        var grouped = Dictionary(grouping: paData, by:{$0.key})

        
        struct Item {
            let key: String
            let sum: Int
        }

        let resultArray = grouped.keys.map { (key) -> Item in
            let value = grouped[key]!
            return Item(key: key, sum: value.map{$0.facings}.reduce(0, +))
        }  
        
        // Find the unique records based on pCode/aCode properties - very fast takes 0.1 second
        let unique = Set<PAData>(paData)

        // Now we need to combined so we have the original properties as well as the sum but no duplicates - slow
        let results = unique.map({ rec -> PAData in
            let sum = resultArray.first(where: {$0.key == rec.key})?.sum ?? rec.facings
            return PAData(brandCode: rec.brandCode, assortmentCode: rec.assortmentCode, productCode: rec.productCode, productCategory: rec.productCategory, productDescription: rec.productDescription, facings: sum)
        })
  }
struct PAData:equalable,Hashable{
让pCode:String
让代码:字符串
计数:Int
变量键:字符串{
返回pCode+“:”+aCode
}
静态函数==(左:PAData,右:PAData)->Bool{
返回
lhs.pCode==rhs.pCode&&
lhs.aCode==rhs.aCode
}
func散列(放入散列程序:inout散列程序){
hasher.combine(pCode)
联合收割机(aCode)
}
}
//按aCode、pCode和总和计数分组
func calcSum(){
var grouped=Dictionary(分组:paData,按:{$0.key})
结构项{
让键:字符串
求和:Int
}
让resultArray=grouped.keys.map{(key)->项位于
让值=分组[键]!
返回项(key:key,sum:value.map{$0.facings}.reduce(0,+))
}  
//根据pCode/aCode属性查找唯一记录-非常快需要0.1秒
let unique=Set(paData)
//现在我们需要合并,这样我们就有了原始属性和和,但没有重复-慢
让results=unique.map({rec->PAData in)
让sum=resultArray.first(其中:{$0.key==rec.key})?.sum??rec.facings
返回PAData(品牌代码:rec.brandCode,产品组合代码:rec.schodmentCode,产品代码:rec.productCode,产品类别:rec.productCategory,产品描述:rec.productDescription,外观:总和)
})
}

这应该可以做到:

func calcSum2(_ paData: [PAData]) -> [PAData] {
    let date = Date()
    let grouped = Dictionary(grouping: paData) { aPaData in
        return PAData(pCode: aPaData.pCode, aCode: aPaData.aCode, count: -2) //Here it's to take advantage of your Hashable
    }
    let resultArray = grouped.compactMap { (key: PAData, values: [PAData]) -> PAData in
        let sum = values.reduce(into: 0, { $0 += $1.count })
        return PAData(pCode: key.pCode, aCode: key.aCode, count: sum)
    }
    return resultArray
}
您的代码有什么问题:

let unique = Set<PAData>(paData)
for key in unique {
            
    let sum = paData.filter({$0.pCode == key.pCode && $0.aCode == key.aCode}).map({$0.count}).reduce(0, +)

    let summary = PAData(pCode: key.pCode, aCode: key.aCode, count: sum)

    resultArray.append(summary)
}
结果很奇怪:

Dictionary:
{
    "PAData(pCode: \"a\", aCode: \"b\", count: -2)" =     (
        "PAData(pCode: \"a\", aCode: \"b\", count: 2)",
        "PAData(pCode: \"a\", aCode: \"b\", count: 3)"
    );
    "PAData(pCode: \"d\", aCode: \"c\", count: -2)" =     (
        "PAData(pCode: \"d\", aCode: \"c\", count: 2)"
    );
}
Set:
{(
    PAData(pCode: "a", aCode: "b", count: 3),
    PAData(pCode: "d", aCode: "c", count: 2),
    PAData(pCode: "a", aCode: "b", count: 2)
)}

使用
Dictionary.grouping()
和迭代值求和怎么样?@Larme-是的,我刚刚发现了,但似乎没有解决问题-我将更新我的问题,因为我遗漏了该部分。你不是uniquing。通过
aCode
pCode
。测试它,
unique.count
=
paData.count
。这就是为什么它需要时间。另外,在
sum
calculation中,您使用filter对paData进行迭代(因此您有1k个元素…),然后对结果进行迭代(映射,因此如果您发现100个元素匹配),然后使用reduce对相同的计数(100)进行迭代no my unique.count!=paData.count“records:17797 unique:17363”-大致正确。通常只有一个或两个相同的记录-可能多达10个。遗憾的是,这只需要大约400个记录-但我想不出一种方法来过滤掉,所以只需要重新计算重复的记录。啊,可能是元素计数>1!的地方分组的!?Sheesh calcSum2()似乎很好-大约需要0.1秒!!非常感谢。现在还不清楚Set()在与结构一起使用时是否会查看每个属性,即使该结构是可等式的还是可哈希的。尽管如此,它似乎给出了与calcSum2()相同的汇总总数。
let testArray = [PAData(pCode: "a", aCode: "b", count: 2),
                 PAData(pCode: "a", aCode: "b", count: 3),
                 PAData(pCode: "d", aCode: "c", count: 2)]
let setTest = Set<PAData>(testArray)

print("setTest: \(setTest)")
let groupTest = Dictionary(grouping: testArray) { aPaData in
    return PAData(pCode: aPaData.pCode, aCode: aPaData.aCode, count: -2)
}
print("groupTest: \(groupTest)")
Dictionary:
{
    "PAData(pCode: \"a\", aCode: \"b\", count: -2)" =     (
        "PAData(pCode: \"a\", aCode: \"b\", count: 2)",
        "PAData(pCode: \"a\", aCode: \"b\", count: 3)"
    );
    "PAData(pCode: \"d\", aCode: \"c\", count: -2)" =     (
        "PAData(pCode: \"d\", aCode: \"c\", count: 2)"
    );
}
Set:
{(
    PAData(pCode: "a", aCode: "b", count: 3),
    PAData(pCode: "d", aCode: "c", count: 2),
    PAData(pCode: "a", aCode: "b", count: 2)
)}