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)
})