Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between String interpolation and String concatenation

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?

like image 961
Cœur Avatar asked Sep 02 '26 11:09

Cœur


1 Answers

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
    }
}
like image 91
Cœur Avatar answered Sep 04 '26 01:09

Cœur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!