更短的替代三元生成空字符串如果 nil?
Shorter Alternative to ternary to generate empty string if nil?
我有一个 Double?
类型的参数。
当这个参数是nil
的时候,我想要一个空字符串
我可以使用 if (variable == nil) ? "" : String(variable!)
,但是有更短的选择吗?
我没有找到简化代码的简单方法。一个想法是像这样创建一个 Double 扩展:
extension Optional where Wrapped == Double {
var asString: String {
self == nil ? "" : String(self!)
}
}
然后您只使用以下 if 条件代替:
variable.asString
使用Optional.map
and the nil-coalescing operator ??
你可以做到
var variable: Double? = 1.0
let string = variable.map { String([=10=]) } ?? ""
如果变量不是 nil
,则调用闭包(并返回字符串),否则 map
returns nil
并且表达式的计算结果为空字符串.
如果你想在另一个字符串中使用结果字符串,像这样:
let string = "The value is: \(variable)"
并可能指定当 variable
为 nil
时要打印的内容:
let string = "The value is: \(variable, nil: "value is nil")"
你可以为 String.StringInterpolation 编写一个方便的通用扩展,它接受任何类型的值并打印它,如果它是可选的并且 nil
它打印指定的“默认”字符串:
extension String.StringInterpolation {
mutating func appendInterpolation<T>(_ value: T?, `nil` defaultValue: @autoclosure () -> String) {
if let value = value {
appendLiteral("\(value)")
} else {
appendLiteral(defaultValue())
}
}
}
示例:
var d: Double? = nil
print("Double: \(d, nil: "value is nil")")
d = 1
print("Double: \(d, nil: "value is nil")")
let i = 1
print("Integer: \(i, nil: "value is nil")")
控制台输出:
Double: value is nil
Double: 1.0
Integer: 1
只是为了好玩,一种涵盖所有符合 LosslessStringConvertible 类型的通用方法:
extension LosslessStringConvertible {
var string: String { .init(self) }
}
extension Optional where Wrapped: LosslessStringConvertible {
var string: String { self?.string ?? "" }
}
var double = Double("2.7")
print(double.string) // "2.7\n"
属性 包装器应该可以帮助您获得所需的结果 - 属性 包装器有一个特殊的变量 wrappedValue和 projectedValue 可以添加一层分离并允许您包装自定义逻辑。
wrappedValue - 使用 getter 和 setter 操作此变量。它在我们的例子中用得很少,因为它是 Double?类型
projectedValue - 这将是我们的重点,因为在我们的案例中我们可以使用此变量将 Double 投影为字符串。
实现如下
@propertyWrapper
struct DoubleToString {
private var number: Double = 0.0
var projectedValue: String = ""
var wrappedValue: Double?{
get {
return number // Not really required
}
set {
if let value = newValue { // Check for nil
projectedValue = value.description // Convert to string
number = value
}
}
}
}
现在我们创建一个使用这个包装器的结构。
struct NumbersTest {
@DoubleToString var number1: Double?
@DoubleToString var number2: Double?
}
在运行下面的代码中,我们得到了想要的结果。 $number1 给我们 projectedValue
如果我们忽略 $ 符号,我们会得到 wrappedvalue
var numbersTest = NumbersTest()
numbersTest.number1 = 25.0
numbersTest.number2 = nil
print(numbersTest.$number1) //"25.0"
print(numbersTest.$number2) //""
通过使用 属性 包装器,您可以保持变量的互操作性,从而轻松获取 Double 和 String 值。
我有一个 Double?
类型的参数。
当这个参数是nil
的时候,我想要一个空字符串
我可以使用 if (variable == nil) ? "" : String(variable!)
,但是有更短的选择吗?
我没有找到简化代码的简单方法。一个想法是像这样创建一个 Double 扩展:
extension Optional where Wrapped == Double {
var asString: String {
self == nil ? "" : String(self!)
}
}
然后您只使用以下 if 条件代替:
variable.asString
使用Optional.map
and the nil-coalescing operator ??
你可以做到
var variable: Double? = 1.0
let string = variable.map { String([=10=]) } ?? ""
如果变量不是 nil
,则调用闭包(并返回字符串),否则 map
returns nil
并且表达式的计算结果为空字符串.
如果你想在另一个字符串中使用结果字符串,像这样:
let string = "The value is: \(variable)"
并可能指定当 variable
为 nil
时要打印的内容:
let string = "The value is: \(variable, nil: "value is nil")"
你可以为 String.StringInterpolation 编写一个方便的通用扩展,它接受任何类型的值并打印它,如果它是可选的并且 nil
它打印指定的“默认”字符串:
extension String.StringInterpolation {
mutating func appendInterpolation<T>(_ value: T?, `nil` defaultValue: @autoclosure () -> String) {
if let value = value {
appendLiteral("\(value)")
} else {
appendLiteral(defaultValue())
}
}
}
示例:
var d: Double? = nil
print("Double: \(d, nil: "value is nil")")
d = 1
print("Double: \(d, nil: "value is nil")")
let i = 1
print("Integer: \(i, nil: "value is nil")")
控制台输出:
Double: value is nil
Double: 1.0
Integer: 1
只是为了好玩,一种涵盖所有符合 LosslessStringConvertible 类型的通用方法:
extension LosslessStringConvertible {
var string: String { .init(self) }
}
extension Optional where Wrapped: LosslessStringConvertible {
var string: String { self?.string ?? "" }
}
var double = Double("2.7")
print(double.string) // "2.7\n"
属性 包装器应该可以帮助您获得所需的结果 - 属性 包装器有一个特殊的变量 wrappedValue和 projectedValue 可以添加一层分离并允许您包装自定义逻辑。
wrappedValue - 使用 getter 和 setter 操作此变量。它在我们的例子中用得很少,因为它是 Double?类型
projectedValue - 这将是我们的重点,因为在我们的案例中我们可以使用此变量将 Double 投影为字符串。
实现如下
@propertyWrapper
struct DoubleToString {
private var number: Double = 0.0
var projectedValue: String = ""
var wrappedValue: Double?{
get {
return number // Not really required
}
set {
if let value = newValue { // Check for nil
projectedValue = value.description // Convert to string
number = value
}
}
}
}
现在我们创建一个使用这个包装器的结构。
struct NumbersTest {
@DoubleToString var number1: Double?
@DoubleToString var number2: Double?
}
在运行下面的代码中,我们得到了想要的结果。 $number1 给我们 projectedValue
如果我们忽略 $ 符号,我们会得到 wrappedvalue
var numbersTest = NumbersTest()
numbersTest.number1 = 25.0
numbersTest.number2 = nil
print(numbersTest.$number1) //"25.0"
print(numbersTest.$number2) //""
通过使用 属性 包装器,您可以保持变量的互操作性,从而轻松获取 Double 和 String 值。