You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从指定字符串提取子串并将Bob、Mike分别赋值给Player1、Player2?

解决Swift中提取字符串内玩家名字的问题

嘿,我完全明白你想从"Match Between Bob and Mike"里把Bob和Mike分别存入Player1、Player2变量的需求了。你之前的代码方向有点走偏——不仅找的"Between: "和原字符串里的"Between "(没有冒号)不匹配,而且你取的是这个索引之前的内容,这当然拿不到后面的玩家名字啦。咱们换几种更直接靠谱的方式来解决:

方法一:正则表达式(最灵活的方案)

如果你的字符串格式可能有轻微变化(比如大小写、多余空格),正则表达式是最稳妥的选择,能精准匹配捕获目标内容:

let match = "Match Between Bob and Mike"
// 正则模式:匹配固定前缀,然后捕获两个玩家名字
let pattern = "Match Between (\\w+) and (\\w+)"

if let regex = try? NSRegularExpression(pattern: pattern),
   let matchResult = regex.firstMatch(in: match, range: NSRange(match.startIndex..., in: match)) {
    // 提取第一个捕获组(对应Bob)
    let player1Range = Range(matchResult.range(at: 1), in: match)!
    let player1 = String(match[player1Range])
    // 提取第二个捕获组(对应Mike)
    let player2Range = Range(matchResult.range(at: 2), in: match)!
    let player2 = String(match[player2Range])
    
    print("Player1: \(player1), Player2: \(player2)") // 输出:Player1: Bob, Player2: Mike
}

这里的(\w+)会匹配由字母、数字组成的名字,如果你需要支持带空格的名字(比如"Bob Smith"),可以把模式改成"Match Between ([^and]+) and (.+)"来适配。

方法二:字符串分割(最直观的方案)

如果你的字符串格式完全固定(必须是"Match Between X and Y"的结构),直接分割字符串会更简单易懂:

let match = "Match Between Bob and Mike"
// 第一步:按"Between "分割,取后面的部分
guard let afterBetween = match.components(separatedBy: "Between ").last else {
    print("格式不匹配")
    return
}
// 第二步:按" and "分割成两个名字
let players = afterBetween.components(separatedBy: " and ")
if players.count == 2 {
    let player1 = players[0]
    let player2 = players[1]
    print("Player1: \(player1), Player2: \(player2)")
} else {
    print("格式不匹配")
}

这种方法代码量少,逻辑清晰,适合格式完全可控的场景。

方法三:基于你写的扩展调整逻辑(手动索引操作)

如果你坚持想用自己写的StringProtocol扩展,那需要调整逻辑,拿到"Between "结束后的内容,再定位" and "的位置来截取名字:

let match = "Match Between Bob and Mike"

// 先找到"Between "的结束索引
if let betweenEndIndex = match.endIndex(of: "Between ") {
    let substringAfterBetween = match[betweenEndIndex...]
    // 找到" and "在后续子串中的起始索引
    if let andStartIndex = substringAfterBetween.index(of: " and ") {
        // 计算"and"在原字符串中的绝对位置
        let absoluteAndStart = match.index(betweenEndIndex, offsetBy: match.distance(from: substringAfterBetween.startIndex, to: andStartIndex))
        // 截取Player1:从Between结束到and开始的位置
        let player1 = String(match[betweenEndIndex..<absoluteAndStart])
        // 截取Player2:从and结束的位置到字符串末尾
        let absoluteAndEnd = match.index(absoluteAndStart, offsetBy: " and ".count)
        let player2 = String(match[absoluteAndEnd...])
        
        print("Player1: \(player1), Player2: \(player2)")
    }
}

// 你的StringProtocol扩展保留不变
extension StringProtocol {
    func index<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.lowerBound
    }
    func endIndex<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index? {
        range(of: string, options: options)?.upperBound
    }
    func indices<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Index] {
        ranges(of: string, options: options).map(\.lowerBound)
    }
    func ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>] {
        var result: [Range<Index>] = []
        var startIndex = self.startIndex
        while startIndex < endIndex,
            let range = self[startIndex...]
                .range(of: string, options: options) {
                result.append(range)
                startIndex = range.lowerBound < range.upperBound ? range.upperBound :
                    index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return result
    }
}

不过这种方法相对繁琐,除非你有特殊需求要手动操作字符串索引,否则更推荐前两种方案。

内容的提问来源于stack exchange,提问作者Anish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:30:57