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

Swift中按特定范围分割字符串并生成指定数组及重构语句

Hey there! Let's work through this step by step to get all your desired outputs sorted out, including fixing the OutputOutsideM issue and generating Output3 and the final reconstructed sentence.

First, Let's Define Our Base Variables

We'll start with your original sentence and reusable markers to keep code clean:

let sentence = "Str1 {M} Str2 {/M} Str3 {M} Str4 {/M} {M} Str5 {/M} Str6 {M} Str7 {/M}"
let startMarker = "{M}"
let endMarker = "{/M}"
let escapedStart = NSRegularExpression.escapedPattern(for: startMarker)
let escapedEnd = NSRegularExpression.escapedPattern(for: endMarker)

1. Get OutputBetweenM (Your Working Code, Optimized)

Your original code already works, but we can trim whitespace to match your expected output exactly:

let betweenRegex = "(?<=\(escapedStart))(.*?)(?=\(escapedEnd))"
let betweenRanges = sentence.ranges(of: betweenRegex, options: .regularExpression)
let outputBetweenM = betweenRanges.map { sentence[$0].trimmingCharacters(in: .whitespaces) }
print(outputBetweenM) // ["Str2", "Str4", "Str5", "Str7"] ✅

2. Fix OutputOutsideM

The issue with your original code was leftover empty/whitespace-only strings from consecutive {M} blocks. We'll filter those out:

let blockRegex = escapedStart + ".*?" + escapedEnd
let blockRanges = sentence.ranges(of: blockRegex, options: .regularExpression)
var tempSentence = sentence

// Replace all {M}...{/M} blocks with newlines
for range in blockRanges.reversed() {
    tempSentence.replaceSubrange(range, with: "\n")
}

// Split and filter out empty/whitespace-only entries
let outputOutsideM = tempSentence.components(separatedBy: .newlines)
    .filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
    .map { $0.trimmingCharacters(in: .whitespaces) } // Optional: trim extra spaces if needed
print(outputOutsideM) // ["Str1", "Str3", "Str6"] ✅

3. Generate OutputBetweenM_Edited

This is straightforward—just apply your editing logic to each entry in outputBetweenM (we'll use appending "Edited" as your example shows):

let outputBetweenM_Edited = outputBetweenM.map { "\($0)Edited" }
print(outputBetweenM_Edited) // ["Str2Edited", "Str4Edited", "Str5Edited", "Str7Edited"] ✅

4. Generate Output3 and Final_sentence

To build these, we'll split the original sentence into alternating "outside" content and {M}...{/M} blocks, then replace the blocks with their edited versions while preserving order:

// Regex to split the sentence into either {M}...{/M} blocks or outside content
let splitRegex = "(\(blockRegex))|(.*?)(?=\(escapedStart)|$)"
let splitRanges = sentence.ranges(of: splitRegex, options: .regularExpression)

var output3: [String] = []
var finalSentenceParts: [String] = []
var betweenIndex = 0 // Track which edited between content to use

for range in splitRanges {
    let part = sentence[range]
    if part.hasPrefix(startMarker) && part.hasSuffix(endMarker) {
        // Handle {M}...{/M} blocks: use edited content
        let editedContent = outputBetweenM_Edited[betweenIndex]
        output3.append(editedContent)
        finalSentenceParts.append("\(startMarker) \(editedContent) \(endMarker)")
        betweenIndex += 1
    } else {
        // Handle outside content: add only if it's not empty
        let trimmedPart = part.trimmingCharacters(in: .whitespaces)
        if !trimmedPart.isEmpty {
            output3.append(trimmedPart)
            finalSentenceParts.append(part)
        }
    }
}

let finalSentence = finalSentenceParts.joined()

print(output3) // ["Str1", "Str2Edited", "Str3", "Str4Edited", "Str5Edited", "Str6", "Str7Edited"] ✅
print(finalSentence) // "Str1 {M} Str2Edited {/M} Str3 {M} Str4Edited {/M} {M} Str5Edited {/M} Str6 {M} Str7Edited {/M}" ✅

Don't Forget Your ranges(of:) Extension

Keep this handy extension you're using for regex range matching:

extension String {
    func ranges(of string: String, options: CompareOptions = .literal) -> [Range<Index>] {
        var result: [Range<Index>] = []
        var start = startIndex
        while let range = range(of: string, options: options, range: start..<endIndex) {
            result.append(range)
            start = range.lowerBound < range.upperBound ? range.upperBound : index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        }
        return result
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:50:39