Arrays 将对象数组转换为累积字典

Arrays 将对象数组转换为累积字典,arrays,swift,dictionary,Arrays,Swift,Dictionary,我有一个叫person的结构 然后我创建一个名为 让人物:[人物]=[人物角色,1,人物角色,3,人物B,5] 如您所见,这里有两个同名的对象a 现在我想把这本书变成一本累积字典,它显示了每个人的总分。在这种情况下 dict={a:43+1,b:5} 我知道我违反了OO设计规则。 谢谢您可以通过两个步骤来实现这一点:1将分组放入词典,2将分组的总分相加: // grouping = { "a": [person("a", 1), person("a", 2)], "b": [person("b"

我有一个叫person的结构

然后我创建一个名为 让人物:[人物]=[人物角色,1,人物角色,3,人物B,5]

如您所见,这里有两个同名的对象a

现在我想把这本书变成一本累积字典,它显示了每个人的总分。在这种情况下 dict={a:43+1,b:5}

我知道我违反了OO设计规则。
谢谢

您可以通过两个步骤来实现这一点:1将分组放入词典,2将分组的总分相加:

// grouping = { "a": [person("a", 1), person("a", 2)], "b": [person("b": 3)]
let grouping = Dictionary.init(grouping: people, by: { person in person.name })

let dict = grouping.mapValues { group in 
   group.reduce(0, { sum, person in sum + person.score })
}
或者以更短但更神秘的形式:

let d = Dictionary.init(grouping: people, by: { $0.name })
                  .mapValues{ $0.reduce(0, $0 + $1.score ) }

这里有一个基本的建模问题。你的struct person实际上并没有为一个人建模。它模拟了一些类似于圆结果的东西

我会重构它,让一个玩家真正模拟一个人,只使用name:String这样的字段,并生成一个包含winner:Player和score:score的RoundResult


从这里,你可以在玩家身上添加一个分数变量,它实际上模拟了玩家的分数,而不仅仅是单轮/游戏/比赛/任何东西中的一小部分。让我带你看一下这个的一些迭代

最基本的是直截了当的方法

var dict=[String:Int] 为人处事{ 如果let score=dict[person.name]{ //如果此人在dict中已有分数,则将此新分数添加到dict中。 dict[person.name]=分数+person.score }否则{ //如果这是此人的第一个分数,则将此人添加到口述中。 dict[person.name]=person.score } } 接下来,我们将使用运算符组合if条件的两部分

var dict=[String:Int] 为人处事{ //将新分数添加到该人员的现有分数中。如果没有现有分数 //分数,然后默认为0并添加新分数。 dict[person.name,默认值:0]+=person.score } 最后,使用以摆脱for循环,请参见

//将人们的名字和累积分数减少到字典中。 让dict=people.reduceinto:[String:Int]{result,person-in 结果[person.name,默认值:0]+=person.score }
顺便说一句,Swift中的类型名称应该是大写的。let people=[a,1,a,3,b,5]。mapPerson.initlet dict:[String:Int]=.initpeople.map{$0.name,$0.score},uniquingKeysWith:+@LeoDabus Nice!谢谢你,杰弗里。我在寻找如何使用你教给我的reduce。这对我帮助很大。如果这个答案解决了你的问题,请用左边的复选标记将其标记为已接受
let d = Dictionary.init(grouping: people, by: { $0.name })
                  .mapValues{ $0.reduce(0, $0 + $1.score ) }
struct Player: Hashable { // Perhaps should be a class, if names aren't unique.
    let name: String
}

struct RoundResult {
    let winner: Player
    let score: Int
}

let playerA = Player(name: "a")
let playerB = Player(name: "b")

let roundResults = [
    RoundResult(winner: playerA, score: 1),
    RoundResult(winner: playerA, score: 3),
    RoundResult(winner: playerB, score: 5),
]

let scoresByPlayer = Dictionary(grouping: roundResults, by: \.winner)
    .mapValues { roundResults -> Int in
        let scores = roundResults.lazy.map(\.score)
        return scores.reduce(0, +)
    }

print(scoresByPlayer)