swiftnspredicatensexpression

String format parameters binding dictionary


Is there any built-in solution that allows to substitute strings in a manner of NSExpression does (i.e. with a binding dictionary provided)?

So instead of:

let s = String(format: "%@ %@", arguments: ["foo", "bar"]) // "foo bar"

we have:

let s = String(format: "$foo $bar", ["foo": "hello", "bar": "world"]) // hello world

P.S. I'm aware of replaceOccurrences, I need NSExpression style substitution. Thanks!


Solution

  • As already mentioned by matt you would need to implement your own method. You can use a regex to match the ranges of all keys of your dictionary that starts with a dollar sign "\\$\\w+" and use the method "ranges(of:)" of this answer to replace the subranges of your string creating a custom initializer extending String:

    extension String {
        init(format: String, _ dictionary: [String: String]) {
            var result = format
            for range in format.ranges(of: "\\$\\w+", options: .regularExpression).reversed() {
                result.replaceSubrange(range, with: dictionary[String(format[range].dropFirst())] ?? "")
            }
            self = result
        }
    }
    

    Playground testing:

    let result = String(format: "$foo $bar", ["foo": "hello", "bar": "world"])
    print(result)   // "hello world"