字符串插值和字符串连接之间的区别 [英] Difference between String interpolation and String concatenation

查看:153
本文介绍了字符串插值和字符串连接之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当专门处理非可选的String值时,字符串插值和字符串串联有什么区别?

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

  • 在任何情况下displayNameByConcatenationdisplayNameByInterpolation是不同的吗?像长长的unicode字符串一样?
  • 在上面的示例中,是否可以以某种方式覆盖运算符+的行为或插值行为以使其与众不同?
  • 一个比另一个快/慢吗?
    • 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?
    • 请注意,通过此问题,我们可以了解到该字符串插值将使用CustomStringConvertible的description.但是String串联(运算符+)是否也调用description?

      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?

      推荐答案

      从速度的角度来看,要区分级联(value1 + "-" + value2)和插值("\(value1)-\(value2)"),结果可能取决于对获取最终的字符串.

      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.

      我在iPhone 8上的结果显示:

      My results on an iPhone 8 show that:

      • 如果大约< 30个子字符串连接在一起,则连接速度更快
      • 如果大约有30个以上的子字符串要附加在一起,则插值会更快

      谢谢塞伦斯(Sirens)弄清楚一个并不一定总是比另一个要快!

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

      这篇关于字符串插值和字符串连接之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆