Difference between String interpolation and String concatenation

孤者浪人 提交于 2020-02-20 06:10:27

问题


When specifically dealing with non-optional String values, what could be the difference between String interpolation and String concatenation?

struct MyModel {
    let value1: String
    let value2: String
    var displayNameByConcatenation: String {
        return value1 + "-" + value2
    }
    var displayNameByInterpolation: String {
        return "\(value1)-\(value2)"
    }
}
  • Is there going to be any case where displayNameByConcatenation and displayNameByInterpolation are different? Like on long unicode strings?
  • Is it possible to somehow override the behavior of operator + or the behavior of interpolation to make them different in above example?
  • Is one faster/slower than the other?

Note that from this question we learn that string interpolation will use the description of a CustomStringConvertible. But does String concatenation (operator +) also calls the description?


回答1:


From a speed point of view, to differentiate concatenation (value1 + "-" + value2) and interpolation ("\(value1)-\(value2)"), results may depend on the number of operations done to obtain the final string.

My results on an iPhone 8 show that:

  • if there is roughly < 30 substrings to attach together, then concatenation is faster
  • if there is roughly > 30 substrings to attach together, then interpolation is faster

Thank you Sirens for figuring out that one wasn't always faster than the other!

Try it yourself (and don't forget to adapt the tested character set and iterations for your needs):

import UIKit

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        DispatchQueue.global(qos: .default).async {
            ViewController.buildDataAndTest()
        }
    }

    private static func buildDataAndTest(times: Int = 1_000) {
        let characterSet = CharacterSet.alphanumerics
        characterSet.cacheAllCharacters()
        let data: [(String, String)] = (0 ..< times).map { _ in
             (characterSet.randomString(length: 50), characterSet.randomString(length: 20))
        }
        _ = testCIA(data)
        _ = testInterpol(data)
        print("concatenation: " + String(resultConcatenation))
        print("interpolation: \(resultInterpolation)")
    }

    /// concatenation in array
    static var resultConcatenation: CFTimeInterval = 0
    private static func testCIA(_ array: [(String, String)]) -> String {
        var foo = ""
        let start = CACurrentMediaTime()
        for (a, b) in array {
            foo = foo + " " + a + "+" + b
        }
        resultConcatenation = CACurrentMediaTime() - start
        return foo
    }

    /// interpolation
    static var resultInterpolation: CFTimeInterval = 0
    private static func testInterpol(_ array: [(String, String)]) -> String {
        var foo = ""
        let start = CACurrentMediaTime()
        for (a, b) in array {
            foo = "\(foo) \(a)+\(b)"
        }
        resultInterpolation = CACurrentMediaTime() - start
        return foo
    }
}

extension CharacterSet {
    static var cachedCharacters: [Character] = []

    public func cacheAllCharacters() {
        CharacterSet.cachedCharacters = characters()
    }

    /// extracting characters
    /// https://stackoverflow.com/a/52133647/1033581
    public func characters() -> [Character] {
        return codePoints().compactMap { UnicodeScalar($0) }.map { Character($0) }
    }
    public func codePoints() -> [Int] {
        var result: [Int] = []
        var plane = 0
        for (i, w) in bitmapRepresentation.enumerated() {
            let k = i % 8193
            if k == 8192 {
                plane = Int(w) << 13
                continue
            }
            let base = (plane + k) << 3
            for j in 0 ..< 8 where w & 1 << j != 0 {
                result.append(base + j)
            }
        }
        return result
    }

    // http://stackoverflow.com/a/42895178/1033581
    public func randomString(length: Int) -> String {
        let charArray = CharacterSet.cachedCharacters
        let charArrayCount = UInt32(charArray.count)
        var randomString = ""
        for _ in 0 ..< length {
            randomString += String(charArray[Int(arc4random_uniform(charArrayCount))])
        }
        return randomString
    }
}



回答2:


"Concatenation allows you to combine to strings together and it only works on two strings."

An update. Not sure what earlier versions of Swift allowed, but currently you can concatenate more than 2 Strings together in the same statement:

let str = "Hi, my name is "

var concat = str + "2" + "3" + "4" + "5" + " works" //displays "Hi, my name is 2345 works"

Because both operands of + need to be Strings, you have to do a little extra work if you want to add a number to a String:

var concat2 = str + String(2) //displays "Hi, my name is 2"

Reason why interpolation rather than concatenation, here's a quote from Apple's intro for interpolation: "String interpolation is a way to construct a new String value from a mix of constants, variables, literals, and expressions" In other words, you can use interpolation with numbers, booleans, etc. without first turning them into Strings, which you would have to do if you used concatenation.




回答3:


string interpolation:

  • less typing
  • Internally calls to string
  • faster during the run time

one disadvantage:

  • delimit your string

Both interpolation and concatenation has its own strength and weakness

Need to use concatenation with predefined string to get better performance



来源:https://stackoverflow.com/questions/42849545/difference-between-string-interpolation-and-string-concatenation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!