Swift 用另一个数组过滤结构内的数组
Swift filter an array inside a struct by another array
我有一组配置文件(从自定义结构定义),在其中,我有一个 [String] 兴趣。
我想过滤掉所有与一系列偏好不匹配的配置文件,但我的过滤似乎无法正常工作。
我得到的错误是
"Cannot convert value of type '[String]' to expected argument type 'String'.
我错过了什么?
一旦完成,我希望 userProfiles
只包含 John 和 Harry。
struct Profile {
var name: String
var interests: [String]
}
var userProfiles: [Profile] = [
Profile(name: "John", interests: ["Basketball", "Football", "Rowing"]),
Profile(name: "Andrew", interests: ["Cycling", "Swimming", "Boxing"]),
Profile(name: "Harry", interests: ["Hockey", "Baseball"])
]
let preferenceInterests = ["Basketball", "Hockey"]
userProfiles = userProfiles.filter({ (userProfile) -> Bool in
print("\(userProfile.name): \(userProfile.interests)")
return preferenceInterests.contains(userProfile.interests) //error here
})
问题是 userProfile.interests
本身就是一个数组。根据您的示例和 John 和 Harry 的预期输出,您实际上想要实现的似乎是保留与您的 preferenceInterests
输入相比具有至少 1 个匹配兴趣的用户。
为此,您需要更改 filter
的正文并使用 contains(where:)
而不是 contains
来检查是否存在兴趣匹配。
let filteredUsers = userProfiles.filter { userProfile in
preferenceInterests.contains(where: { interest in userProfile.interests.contains(interest) })
}
你的问题是 userProfile.interests
是一个数组,所以它不会是包含 String
.
的 preferencesInterests
的元素
如果您考虑一下,您是在尝试查看两组兴趣是否有共同点。这是 Set
路口。 Sets
为此目的比数组更有效,因为检查包含是 O(1) 而不是 O(n)。
把preferenceIntests
变成Set<String>
可以用.isDisjoint(with:)
看看有没有共同爱好。一旦 Swift 找到一个共同点,它就会 return false
因为这些集合包含一个共同元素并且不相交。你会想要反转它,因为你想要 return true
:
的共同兴趣
let preferenceInterests: Set = ["Basketball", "Hockey"]
userProfiles = userProfiles.filter({ (userProfile) -> Bool in
print("\(userProfile.name): \(userProfile.interests)")
return !preferenceInterests.isDisjoint(with: userProfile.interests)
})
我有一组配置文件(从自定义结构定义),在其中,我有一个 [String] 兴趣。
我想过滤掉所有与一系列偏好不匹配的配置文件,但我的过滤似乎无法正常工作。
我得到的错误是
"Cannot convert value of type '[String]' to expected argument type 'String'.
我错过了什么?
一旦完成,我希望 userProfiles
只包含 John 和 Harry。
struct Profile {
var name: String
var interests: [String]
}
var userProfiles: [Profile] = [
Profile(name: "John", interests: ["Basketball", "Football", "Rowing"]),
Profile(name: "Andrew", interests: ["Cycling", "Swimming", "Boxing"]),
Profile(name: "Harry", interests: ["Hockey", "Baseball"])
]
let preferenceInterests = ["Basketball", "Hockey"]
userProfiles = userProfiles.filter({ (userProfile) -> Bool in
print("\(userProfile.name): \(userProfile.interests)")
return preferenceInterests.contains(userProfile.interests) //error here
})
问题是 userProfile.interests
本身就是一个数组。根据您的示例和 John 和 Harry 的预期输出,您实际上想要实现的似乎是保留与您的 preferenceInterests
输入相比具有至少 1 个匹配兴趣的用户。
为此,您需要更改 filter
的正文并使用 contains(where:)
而不是 contains
来检查是否存在兴趣匹配。
let filteredUsers = userProfiles.filter { userProfile in
preferenceInterests.contains(where: { interest in userProfile.interests.contains(interest) })
}
你的问题是 userProfile.interests
是一个数组,所以它不会是包含 String
.
preferencesInterests
的元素
如果您考虑一下,您是在尝试查看两组兴趣是否有共同点。这是 Set
路口。 Sets
为此目的比数组更有效,因为检查包含是 O(1) 而不是 O(n)。
把preferenceIntests
变成Set<String>
可以用.isDisjoint(with:)
看看有没有共同爱好。一旦 Swift 找到一个共同点,它就会 return false
因为这些集合包含一个共同元素并且不相交。你会想要反转它,因为你想要 return true
:
let preferenceInterests: Set = ["Basketball", "Hockey"]
userProfiles = userProfiles.filter({ (userProfile) -> Bool in
print("\(userProfile.name): \(userProfile.interests)")
return !preferenceInterests.isDisjoint(with: userProfile.interests)
})