下面是我的自定义对象类。
class UserGroups: NSObject {
let groupName: String
let users: [CheckIn]?
init(json:JSON) {
self.groupName = json[Constants.Models.UserGroups.groupName].stringValue
self.users = UserGroups.getUserGroupsList(jsonArray: json[Constants.Models.UserGroups.users].arrayValue)
}
class func getUserGroupsList(jsonArray: [JSON]) -> [CheckIn]{
return jsonArray.flatMap({ (jsonItem: JSON) -> CheckIn in
return CheckIn(json: jsonItem)
})
}
}
我有一组上面的自定义对象。如何通过合并具有相同 groupName 的每个对象的用户,将两个或多个自定义对象合并为一个对象。
以下是我的CheckIn模型:
类CheckIn:NSObject {
let id: String
let firstName: String
let lastName: String
let latitude: String
let longitude: String
let hint: String
init(json: JSON) {
self.id = json[Constants.Models.CheckIn.id].stringValue
self.firstName = json[Constants.Models.CheckIn.firstName].stringValue
self.lastName = json[Constants.Models.CheckIn.lastName].stringValue
self.hint = json[Constants.Models.CheckIn.hint].stringValue
self.latitude = json["location"][Constants.Models.CheckIn.latitude].stringValue
self.longitude = json["location"][Constants.Models.CheckIn.longitude].stringValue
}
}
id 字段在CheckIn中不是唯一的。
答案 0 :(得分:2)
这是一个略微简化的示例,展示了如何组合具有相同组名的组。
这是UserGroup
课程。 users
现在是一个变量(var
),因为我们将向组中添加元素以组合它们。
class UserGroups: NSObject {
let groupName: String
var users: [String]?
init(groupName: String, users: [String]?) {
self.groupName = groupName
self.users = users
}
}
以下是三组,其中两组共享相同的组名Blues
。
let group1 = UserGroups(groupName: "Blues", users: ["Tom", "Huck", "Jim"])
let group2 = UserGroups(groupName: "Reds", users: ["Jo", "Ben", "Tommy"])
let group3 = UserGroups(groupName: "Blues", users: ["Polly", "Watson", "Douglas"])
接下来,我们将所有组都放在一个数组中。
let allGroups = [group1, group2, group3]
在这里,我们使用Swift的reduce函数来允许我们将数组简化为只有具有唯一组名的组。
let compacted = allGroups.reduce([UserGroups](), { partialResult, group in
var dupe = partialResult.filter {$0.groupName == group.groupName }.first
if let dupeGroup = dupe {
dupeGroup.users?.append(contentsOf: group.users ?? [])
return partialResult
} else {
var newPartialResult = partialResult
newPartialResult.append(group)
return newPartialResult
}
})
现在,阵列已缩减为唯一群组,我们借助Swift的map功能打印出所有群组及其用户。
print(compacted.map { $0.users })
// Prints [
Optional(["Tom", "Huck", "Jim", "Polly", "Watson", "Douglas"]),
Optional(["Jo", "Ben", "Tommy"])
]
答案 1 :(得分:0)
您没有包含CheckIn
模型,但我会假设它具有某种每个用户唯一的ID字段。我们将使用它来创建对象Hashable
:
// Add this to your file outside of the UserGroups class
extension CheckIn: Hashable {
var hashValue: Int { return self.id }
}
使其Hashable
可以将Array
转换为Set
,这不允许重复,并会以非常有效的方式将其删除。
// Change getUserGroupsList as follows
class func getUserGroupsList(jsonArray: [JSON]) -> [CheckIn] {
return Array(Set(jsonArray.flatMap({ (jsonItem: JSON) -> CheckIn in
return CheckIn(json: jsonItem)
})))
}
顺便说一句,如果你来自另一种语言,Swift会给你很好的类型推断和闭包参数的默认名称($0
是第一个参数)。你可能会使代码变得不那么冗长,但这是一个首选的品味问题。
class func getUserGroupsList(jsonArray: [JSON]) -> [CheckIn] {
return Array(Set(jsonArray.flatMap { CheckIn(json: $0) }))
}
还要考虑您是否确实希望返回值为数组。如果您希望列表始终拥有唯一身份用户,那么使用Set
作为返回类型并放弃转换回Array
这样会更高效:
class func getUserGroupsList(jsonArray: [JSON]) -> Set<CheckIn> {
return Set(jsonArray.flatMap { CheckIn(json: $0) })
}
最后,考虑一下您是否真的需要users
属性是可选的。对于序列类型,通常使用空序列来表示缺少值。根据您的具体情况,这可能会简化您的代码。最终版本如下所示:
class UserGroups: NSObject {
let groupName: String
let users: Set<CheckIn>
init(json:JSON) {
self.groupName = json[Constants.Models.UserGroups.groupName].stringValue
self.users = UserGroups.getUserGroupsList(jsonArray: json[Constants.Models.UserGroups.users].arrayValue)
}
class func getUserGroupsList(jsonArray: [JSON]) -> Set<CheckIn> {
return Set(jsonArray.flatMap { CheckIn(json: $0) })
}
}
需要注意的是Set
不保持项目的顺序。如果组的顺序很重要,我们可以使用此解决方案:
class func getUserGroupsList(jsonArray: [JSON]) -> [CheckIn] {
var encountered: Set<CheckIn> = []
return jsonArray.flatMap { CheckIn(json: $0) }.filter { encountered.update(with: $0) == nil }
}
在这个版本中,我们仍然使用一个集合,但仅用于维护我们已经遇到的一组项目。如果集合中的update
方法已经在集合中,则返回相同的值;如果第一次插入,则返回nil
。我们使用它来将我们的数组过滤到第一次遇到的项目,同时将它们添加到遇到的项目集中,以便在以后再次遇到它们时将它们过滤掉。