字符串插值和字符串连接之间的区别

时间:2017-03-17 05:00:04

标签: swift string swift3 string-concatenation string-interpolation

在专门处理非可选String值时,字符串插值和字符串连接之间可能有什么区别?

struct MyModel {
    let value1: String
    let value2: String
    var displayNameByConcatenation: String {
        return value1 + "-" + value2
    }
    var displayNameByInterpolation: String {
        return "\(value1)-\(value2)"
    }
}
  • 是否会出现displayNameByConcatenationdisplayNameByInterpolation不同的情况?喜欢长的unicode字符串吗?
  • 是否有可能以某种方式覆盖运算符+的行为或插值行为以使它们在上述示例中有所不同?
  • 一个比另一个更快/更慢吗?

请注意,从this question我们了解到字符串插值将使用CustomStringConvertible的description。但String连接(运算符+)是否也会调用description

3 个答案:

答案 0 :(得分:3)

从速度的角度来看,为了区分连接(value1 + "-" + value2)和插值("\(value1)-\(value2)"),结果可能取决于为获得最终字符串而完成的操作数。

我在iPhone 8上的搜索结果显示:

  • 如果大致< 30个子串连接在一起,然后串联更快
  • 如果有大致> 30个子串连接在一起,然后插值更快

感谢警笛发现一个并不总是比另一个更快!

自己尝试(并且不要忘记根据需要调整经过测试的字符集和迭代):

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
    }
}

答案 1 :(得分:0)

字符串插值:

  • 少输入
  • 内部调用字符串
  • 在运行期间更快

一个缺点:

  • 分隔字符串

插值和连接都有自己的优点和缺点

需要使用与预定义字符串的串联来获得更好的性能

答案 2 :(得分:0)

“连接允许您将字符串组合在一起,它只适用于两个字符串。”

更新。不确定Swift的早期版本是什么允许的,但是目前你可以在同一个语句中连接两个以上的字符串:

让str =“嗨,我的名字是”

var concat = str +“2”+“3”+“4”+“5”+“works”//显示“嗨,我的名字是2345作品”

因为+的两个操作数都需要是字符串,如果你想在字符串中添加一个数字,你必须做一些额外的工作:

var concat2 = str + String(2)//显示“嗨,我的名字是2”

插值而不是连接的原因,这里是Apple插值介绍的引用:“字符串插值是一种从常量,变量,文字和表达式的混合构造新String值的方法”换句话说,你可以使用插值与数字,布尔值等,而不先将它们变成字符串,如果使用串联则必须这样做。