微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

给定几个条件,如何有效地搜索字符串数组中的字符串?

如何解决给定几个条件,如何有效地搜索字符串数组中的字符串?

我正在尝试过滤字符串数组并返回基于两个用例匹配的字符串。

案例 1: 仅当 searchString 位于单词的开头时才匹配。

例如,如果我们有一个数组 -> [《拉尔夫破网》、《波西米亚狂想曲》、《蜘蛛侠:平行宇宙》] 我们正在尝试将它与搜索字符串“r”相匹配

在这种情况下,我们应该返回 ["Ralph Breaks The Internet","Bohemian Rhapsody"] 因为 "r" 位于开头,如 ralph 中的 r 和 Rhapsody 中的 r。但是“蜘蛛侠:平行宇宙”不匹配,因为 r 在中间。

情况 2:如果 searchText 的顺序不准确,也匹配。

例如,如果我们有一个数组 -> ["Ralph Breaks The Internet","Bohemian Rhapsody","Spider-Man: Into the Spider-Verse"] 并且我们试图将它与搜索字符串匹配 " Rhapsody Bohemian”,即使顺序不同,它仍然应该匹配。

这是我迄今为止尝试过的:

func searchMovies(_ movieNames: [String],with searchText: String) -> [String] {
    
    var matchedMovies = [String]()
    
    for movie in movieNames {
        
        let movieWords = movie.split(separator: " ")
        let searchTextWords = searchText.split(separator: " ")
        var count = searchTextWords.count
        
        loop:
        for word in movieWords {
            for text in searchTextWords {
                let pattern = "\\b\(text)"
                if let _ = word.range(of: pattern,options: [.regularExpression,.caseInsensitive]) {
                    count -= 1
                }
                if count == 0 {
                    matchedMovies.append(movie)
                    break loop
                }
            }
        }
    }
    
    return matchedMovies
}

我知道这不是一种有效的方法。如果有人能指导我朝某个方向发展,这样我就可以更有效地解决同一件事,那就太好了。

解决方法

对于您的具体情况,您可以像这样格式化您的正则表达式:

"^(?=.*\\bRhapsody)(?=.*\\bBohemian).*$"

为了灵活,你可以这样写你的函数:

func searchMovies(_ movieNames: [String],with searchText: String) -> [String] {
    // split search text into "words"
    let words: [String] = searchText.components(separatedBy: " ")
    
    // start of pattern string
    var pattern: String = "^"
    
    // for each word in search text
    words.forEach { w in
        // append regex to search for words beginning with word
        pattern += "(?=.*\\b\(w))"
    }
    
    // end of pattern string
    pattern += ".*$"
    
    return movieNames.filter { (movie) -> Bool in
        if let _ = movie.range(of: pattern,options: [.regularExpression,.caseInsensitive]) {
            return true
        }
        return false
    }
}

你可以调用它:

    let a: [String] = [
        "Ralph Breaks The Internet","Bohemian Rhapsody","Spider-Man: Into the Spider-Verse"
    ]
    
    let matchingArray = searchMovies(a,with: "Rhapsody Bohemian")

请注意,这将匹配单词的开头(如您使用“r”所示),因此将返回相同的结果:

let matchingArray = searchMovies(a,with: "Rhap Boh")

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。