我在Swift中有两个这样的结构:
struct Friend {
id: Int
name: String
biography: String
profilePicURL: String
}
struct ProfileViews {
id: Int
views: Int
}
我正在尝试根据个人资料([Friend]
)的浏览量对好友([ProfileViews]
)数组进行排序。我该如何根据id来做到这一点,这在两个结构中都是相同的?问题是,有时两个结构都不匹配。例如,某个朋友可能还没有ProfileViews。例如:
Friend(id: 1, name: "PennyWise", biography: "Lorem ipsum", "test.jpg")
Friend(id: 2, name: "Bob", biography: "Dolar sit amet", "test2.jpg")
Friend(id: 3, name: "Dylan", biography: "Yes we can!", "test3.jpg")
ProfileViews(id: 1, views: 23)
ProfileViews(id: 3, views: 12)
然后我想基于视图对[Friend]
数组进行排序,因此ID 1,ID 3,ID2。我该怎么做?我知道sorted(by:)
函数,但似乎只能在[Friend]
数组中执行此操作。但我想使用其他结构中的变量。
答案 0 :(得分:2)
最简单的解决方案是将ProfileViews
的值作为Friend
的属性,或者甚至将概要文件视图作为Int
上的Friend
的属性。< / p>
如果这不可能,那么最简单的解决方案是创建个人资料视图的字典并即时查找它们。
// Create a dictionary that maps from user ids to ProfileViews:
let viewIndex = Dictionary(
profileViews.map { views in
// views.id will be the key, views will be the value
(views.id, views)
}
// If two views values exist with the same user ID, they will be added together
uniquingKeysWith: { views1, views2 -> ProfileViews in
ProfileViews(id: views1.id, views: views1.views + views2.views)
}
)
// Sort friends by looking up the views in the viewIndex
let sortedFriends = friends.sorted(by: { friend1, friend2 -> Bool in
(viewIndex[friend1.id]?.views ?? 0) < (viewIndex[friend2.id]?.views ?? 0)
})
答案 1 :(得分:2)
您可能希望将这些信息永久地合并在一起(通过使views
成为Friend
的一部分),但是如果您希望将它们分开,则仍然可以根据需要完全将它们合并在一起。做一个数据库JOIN:
struct FriendViews {
let friend: Friend
let views: Int
}
let friends: [Friend] = ...
let views: [ProfileViews] = ...
let friendViews = friends.map { (friend) -> FriendViews in
let viewCount = views.first(where: { $0.id == 1 })?.views ?? 0
return FriendViews(friend: friend, views: viewCount)
}
这样,您只需要使用您似乎了解的标准排序工具即可对friendViews进行排序。
答案 2 :(得分:2)
此解决方案将Friend和ProfileView映射到元组,然后再对其进行排序,然后再将其映射回去。
假设两个数组friends
和profiles
:
let sorted = friends.map { friend -> (Friend, Int) in return (friend, profiles.first(where! { $0.id == friend.id })?.views ?? -1) }
.sorted { t1, t2 in t1.1 > t2.1 }
.map { $0.0 }
答案 3 :(得分:1)
这是带有一些复杂性分析的另一个解决方案。假设n = profileViews.count
和m = friends.count
// Count the total views each id has. We use a dictionary
// because dictionary lookup is O(n) compared to an array
// search, which is O(n).
// Complexity: 2 * O(n)
let totalViews = Dictionary(grouping: profileViews, by: { $0.id })
.mapValues { pv in pv.reduce(0, {$0 + $1.views}) }
// Complexity: O(m log m)
let sortedFriends = friends.sorted { f0, f1 in
let view0 = totalViews[f0.id] ?? 0 // O(1)
let view1 = totalViews[f1.id] ?? 0 // O(1)
return view0 > view1
}
总体复杂度:2 * O(n) + O(m log m)