我如何将电影和日期列表解析为 Swift 中的列表?

How would I parse a list of movies and dates into a list in Swift?

我正在做一个项目,我得到了一个用户和他们的生日,以及一个电影列表和这个人去过的日期。一个示例字符串是这样的:"Participant Name: Example name, Birthdate: 01/11/2000, Spiderman 05/15/2021 07/16/2021 08/17/2021 Avengers Infinity War 05/15/2020 07/16/2020 08/17/2020 The Lorax 01/05/2015" 等等。我知道该字符串将包含哪些电影,并且我知道每部电影的最大日期数,但我不知道该人看过这部电影的具体次数。我为生日做了以下操作,这只是因为请求的格式始终与生日相同:

     func FindBirthdate(str: String) -> Date{
//I make sure that the text before birthdate is always converted to DOB 
//in other functions, and that the string is converted 
//to an array seperated by spaces.
         let index = str.firstIndex(of: "DOB:")!
    let birthdate = str[index+1]
    print(birthdate)
    let formatter = DateFormatter()
    formatter.dateFormat = "MM/dd/yyyy"
    formatter.locale = Locale(identifier: "COUNTRY IDENTIFIER")
    formatter.timeZone = TimeZone(identifier: "EXAMPLE")
    return formatter.date(from: birthdate) ?? Date()
     }
    
     
     

但是,正如我之前所说,我不知道用户会看过多少次电影。电影将按相同的顺序排列。我如何将每部电影之间的角色分成该电影的日期?再一次,我的问题是我不知道日期的数量,那么我如何获得每个日期和 return 列表?我研究了一种 ForEach statement,但不确定如何将其集成到字符串中。 This answer suggested that I use regexes, however, this solely focuses on the dates, and not the movies. The string isn't solely made up of dates. I've also taken a look at sample date parsing in Swift,但这只是单个日期。我的问题不是日期转换,而是首先查找和分隔日期。 Meta 上也有人建议我尝试拆分。我看过 Apple Developer 上的 Splitting,这似乎是一个很好的解决方案,但我不确定我会根据什么进行拆分。要再次显示该示例字符串,"Participant Name: Example name, Birthdate: 01/11/2000, Spiderman 05/15/2021 07/16/2021 08/17/2021 Avengers Infinity War 05/15/2020 07/16/2020 08/17/2020 The Lorax 01/05/2015"。电影名称将永远只有这些——它们永远不会有数字。日期也将始终采用相同的 MM/DD/YYYY 格式。名称紧接在日期之前,除 space.

外没有分隔符

之前没有人问过这个问题的原因是,虽然其他问题可能会询问有关日期解析或查找子字符串的问题,但我需要为每部电影和电影标题找到每个单独的日期 - 这是试图找到每部电影的字符串中的每个日期。

这对你有用吗? 我假设您完全遵循示例中的文本格式。

extension String {
    func match(_ regex: String) -> [[String]] {
        let nsString = self as NSString
        return (try? NSRegularExpression(pattern: regex, options: []))?.matches(in: self, options: [], range: NSMakeRange(0, nsString.length)).map { match in
            (0..<match.numberOfRanges).map { match.range(at: [=10=]).location == NSNotFound ? "" : nsString.substring(with: match.range(at: [=10=])) }
        } ?? []
    }
}

然后:


    
    func getName(text: String) -> String? {
        guard let match = text.match("(?<=Participant Name: )(.*)(?=, Birthdate)").first else { return nil }
        return match.first
    }

    func getBirthDay(text: String) -> String? {
        guard let match = text.match("(?<=Birthdate: )(.*)(?=, )").first else { return nil }
        return match.first
    }
    
    func getMovies(text: String) -> [String: [String]] {
        var result: [String: [String]] = [:]
        guard let moviesString = text.match("(?<=Participant Name: \(getName(text: text)!), Birthdate: \(getBirthDay(text: text)!), )(.*)").first?.first else { return result }
        let asArray = moviesString.components(separatedBy: " ")
        var key: String = ""
        var values = [String]()
        var lastKey: String = ""
        for item in asArray {
            if !isDate(item) {
                values.removeAll()
                key += key != "" ? (" " + item) : item
                lastKey = key
                continue
            } else {
                key = ""
                if var existingValues = result[lastKey] {
                    existingValues.append(item)
                    result[lastKey] = existingValues
                } else {
                    result[lastKey] = [item]
                }
            }
            
        }
        
        return result
    }
    
    func isDate(_ string: String) -> Bool {
        return !string.match("[0-9]{2}(/)[0-9]{2}(/)[0-9]{4}").isEmpty
    }

测试:

let text = "Participant Name: Example name, Birthdate: 01/11/2000, Spiderman 05/15/2021 07/16/2021 08/17/2021 Avengers Infinity War 05/15/2020 07/16/2020 08/17/2020 The Lorax 01/05/2015"
        
let movies = getMovies(text: text)

print(">>>> \(movies["Spiderman"])")

输出:

Optional(["05/15/2021", "07/16/2021", "08/17/2021"])