首页 > 解决方案 > Swift - 如何根据匹配值将两个无序的结构数组组合成一个新对象数组?

问题描述

我有两个不同的自定义结构数组(比如说 [NameAndAge] 和 [FullName])。我想将它们组合成一个新对象数组(我们称之为 FullNamesAndAges)。我的想法是遍历它们,匹配名字以创建新对象。

如果我的结构如下所示:

struct NameAndAge {
    let name: String
    let age: Int
}

struct FullName {
    let firstName: String
    let lastName: String
}

我的新对象如下所示:

class PersonViewModel {
    let firstName: String
    let lastName: String
    var age: Int
    // with initializer
}

我将如何做到这一点?现在,我正在使用两张地图,但我想知道是否有更短/更清洁/更高效/更好(插入您喜欢的形容词)的方式来做到这一点?我完全理解这可能是主观的,因为这是一个见仁见智的问题。我只想知道是否有更快的方法来实现这一点。

我目前拥有的:

let namesAndAges: [NameAndAge] = // pretend this is an array of 10+ structs, unordered
let fullNames: [FullName] = // pretend this is an array of 10+ structs, unordered


let people = namesAndAges.compactMap { nameAge in
                        fullNames.compactMap { fullName in
                              if fullName.firstName == nameAge.name {
                                       return PersonViewModel(fullName.firstName, fullName.lastName, nameAge.age)
                              }
                        }
              }

对我来说,这看起来超级草率,这就是为什么我希望有一个“更好”的方法来做到这一点。我不能使用zip,因为它们是无序的。

标签: arraysswiftclassobject

解决方案


您的代码很紧凑,但效率不高。如果您的数组有数千个条目,那么您将进行数百万次比较。

相反,首先创建一个Dictionary允许您NameAndAge根据名称查找记录的方法。字典对于查找非常有效。

然后使用数组中的字典compactMapfullNames创建最终的 s 数组PersonViewModel

let namesAndAges: [NameAndAge] = [] // this is an array of 10+ structs, unordered
let fullNames: [FullName] = [] // this is an array of 10+ structs, unordered

// Create a dictionary to efficiently map name to `NameAndAge` struct
var nameAndAgeLookup = [String : NameAndAge]()
namesAndAges.forEach { nameAndAgeLookup[$0.name] = $0 }

let people = fullNames.compactMap { fullName -> PersonViewModel? in
    guard let age = nameAndAgeLookup[fullName.firstName]?.age else { return nil }
    return PersonViewModel(fullName.firstName, fullName.lastName, age)
}

注意:我假设这只是一个示例,因为由于名称冲突,根据名字查找某人的年龄并不是一个好主意。


推荐阅读