【问题标题】:Swift: math operation on regex capture numbersSwift:对正则表达式捕获数字的数学运算
【发布时间】:2014-11-29 10:36:18
【问题描述】:

我喜欢使用正则表达式将“我跑了 12 英里”改为“我跑了 24 英里”。 “12”可以是任何数字。我使用函数“replace2()”进行数学运算。传递给函数 replace2("$1") 的捕获参数 "$1" 很好。请帮忙!

func replace( str:String, pattern : String, repl:String)->String?{
    let regex = NSRegularExpression .regularExpressionWithPattern(pattern, options: nil,error: nil)
    let replacedString = regex.stringByReplacingMatchesInString( str, options: nil,
        range: NSMakeRange(0, countElements( str)), withTemplate: repl )
    return replacedString

}
replace( "I run 12 miles and walk 12.45 km","\\d+(.\\d+)?", "-")!

func replace2(x: String)->String {
    let xx = x.toInt()! * 2     // error : return nil?
    return String(format: "\(xx)")
}
replace( "I run 12 miles ","(\\d+)", replace2("$1") )!    // error

【问题讨论】:

    标签: regex swift capture


    【解决方案1】:

    在操场上试试这个:

    let str1: NSString = "I run 12 miles"
    let str2 = "I run 12 miles"
    
    let match = str1.rangeOfString("\\d+", options: .RegularExpressionSearch)
    let finalStr = str1.substringWithRange(match).toInt()
    let n: Double = 2.2*Double(finalStr!)
    
    let newStr = str2.stringByReplacingOccurrencesOfString("\\d+", withString: "\(n)", options: NSStringCompareOptions.RegularExpressionSearch, range: nil)
    
    println(newStr) //I run 26.4 miles
    
    
    //or more simply
    let newStr2 = "I run \(n) kilometers"
    //yes, I know my conversion is off
    

    【讨论】:

    • 谢谢。有用。但我尝试将许多(未知)数字相乘,例如
    • “我在 -34F 度下跑了 34 英里和 10.54 公里。”我喜欢将所有 3 个数字乘以 2。
    • 非常感谢。有用。但我尝试使用纯 Swift 并尝试尽可能远离“NS”的东西,除了多余的。您能否将字符串“我在 -34F 度下跑 34 英里和 10.54 公里”中的所有数字加倍到“我在 -68F 度下跑 68 英里和 21.08 公里”。在 Perl 中很简单:"s/(\d+(\.\d+)?)/$1 * 2/ge"
    • 如果你愿意,我可以做一个快速的功能。更长。
    【解决方案2】:

    如果要动态捕获值并根据捕获的值替换它们,则必须使用enumerateMatchesInString。然后,您可以编写一个循环来进行替换:

    func stringWithDoubleNumbers(string: String) -> String {
        // build array of ranges that need replacing
    
        var ranges = [NSRange]()
        let regex  = NSRegularExpression(pattern: "[\\d.]+", options: nil, error: nil) as NSRegularExpression
        regex.enumerateMatchesInString(string, options: nil, range: NSMakeRange(0, countElements(string))) {
            match, flags, stop in
    
            ranges.append(match.range)
        }
    
        var doubledString = NSMutableString(string: string)
    
        // iterate backwards so that location is valid despite other replacements
    
        for range in reverse(ranges) {
            let foundString = doubledString.substringWithRange(range)
    
            if let value = foundString.toInt() {
                let numericString = "\(value * 2)"
                doubledString.replaceCharactersInRange(range, withString: numericString)
            } else {
                let value = NSString(string: foundString).doubleValue
                let numericString = "\(value * 2.0)"
                doubledString.replaceCharactersInRange(range, withString: numericString)
            }
        }
    
        return doubledString
    }
    

    我做了一些额外的逻辑来处理与浮点类型不同的整数值,但如果你不想担心这种复杂性,你可以简化这一点。

    【讨论】:

    • 太棒了!谢谢。
    【解决方案3】:

    // 我用上面的 Steve 和 Rob 代码做实验,我想我可以得到解决简单字符串问题的代码。我仍然遇到复杂字符串的问题。我尝试解析具有各种多个(-20)数字的数据记录,其中整数/双精度数不是任何序列,例如在单个例程中同时处理 str2 和 str3。无论如何感谢史蒂夫和罗布。

    let str2 = "I run 89 miles and 28.576 km"
    let str3 = "I run 89.45 miles and 34 km in 34F degree"
    
    var re = NSRegularExpression(pattern: "(\\d+).* (\\d+\\.\\d+)", options: nil, error: nil)
    var match = re.firstMatchInString(str2, options: nil, range: NSMakeRange(0, countElements(str2)))
    
    var startIndex = advance(str2.startIndex, match.rangeAtIndex(1).location)
    var endIndex   = advance(str2.startIndex, match.rangeAtIndex(1).location + match.rangeAtIndex(1).length)
    let x1 = str2.substringWithRange(Range(start: startIndex, end: endIndex)).toInt()!
    

    x1

    startIndex = advance(str2.startIndex, match.rangeAtIndex(2).location)
    endIndex   = advance(str2.startIndex, match.rangeAtIndex(2).location + match.rangeAtIndex(2).length)
    let x2 = str2.substringWithRange(Range(start: startIndex, end: endIndex))
    let x2x = NSString(string: x2).doubleValue
    let n1 = x1 * 2
    let n2: Double = 2.0 * x2x
    
    str2.stringByReplacingOccurrencesOfString("(\\d+)(.* )(\\d+\\.\\d+)", withString: "\(n1)$2\(n2)", options: NSStringCompareOptions.RegularExpressionSearch, range: nil)
    

    // 我跑了 178 英里和 57.152 公里”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多