Swift 2 - 连接可选字符串的正确方法?

时间:2015-11-24 23:13:54

标签: swift

我们假设我有一个名为Person的{​​{1}}类实例,其personfirst名称属性都是可选字符串。< / p>

现在我想构建一个last字符串,其中只包含它们的名字或姓氏(如果它们全部可用),或者如果我们同时包含它们的名字,那么它们的名字和姓氏都是中间的空间。

fullName

var fullName : String?
if let first = person.first {
    name = first
}
if let last = person.last {
    if name == nil {
        name = last
    } else {
        name! += " " + last
    }
}

我理解选项,但我不能完全围绕着#Sw;&#34;&#34; Swift&#34;思考它们和处理安全展开的方式。我们应该嵌套var name = "" if let first = person.first { name = first } if let last = person.last { name = name.characters.count > 0 ? name + " " + last : last } 吗?是否有更清洁,更多&#34; Swift&#34;这样做的方式? Nil合并似乎是合适的,但我不能想到如何在这种情况下应用它。我无法帮助,但感觉我是以过于复杂的方式进行可选的字符串连接。

10 个答案:

答案 0 :(得分:64)

compactMap在这里工作得很好,与.joined(separator:)结合使用:

let f: String? = "jo"
let l: String? = "smith"

[f,l] // "jo smith"
  .compactMap { $0 }
  .joined(separator: " ")

如果一个是nil

,它之间没有空格
let n: String? = nil

[f,n] // "jo"
  .compactMap { $0 }
  .joined(separator: " ")

答案 1 :(得分:5)

有时简单是最好的:

let first = p.first ?? ""
let last = p.last ?? ""
let both = !first.isEmpty && !last.isEmpty
let full = first + (both ? " " : "") + last

如果没有firstlast,如果有first但没有last,如果有last但没有{{} {1}},如果同时包含firstfirst。我想不出任何其他情况。

这是将这个想法合并到计算变量中的惯用语;作为额外的好处,我允许lastfull以防其他名称nil

nil

答案 2 :(得分:3)

在某个地方,我相信这本快速的书,我遇到了这种模式,从此之前你可以在一个单独的if中使用多个let:

class User {
    var lastName : String?
    var firstName : String?

    var fullName : String {
        switch (firstName, lastName) {
        case (.Some, .Some):
            return firstName! + " " + lastName!

        case (.None, .Some):
            return lastName!

        case (.Some, .None):
            return firstName!

        default:
            return ""
        }
    }

    init(lastName:String?, firstName:String?) {
        self.lastName = lastName
        self.firstName = firstName
    }
}

User(lastName: nil, firstName: "first").fullName        // -> "first"
User(lastName: "last", firstName: nil).fullName         // -> "last"
User(lastName: nil, firstName: nil).fullName            // -> ""
User(lastName: "last", firstName: "first").fullName     // -> "first last"

一个更简洁的解决方案,给出了swift 3.0:

var fullName : String {
    return [ firstName, lastName ].flatMap({$0}).joined(separator:" ")
}

答案 3 :(得分:2)

这是另一种方法:

let name = 
(person.first != nil && person.last != nil) ? 
person.first! + " " + person.last! : 
person.first ?? person.last!

答案 4 :(得分:1)

我喜欢oisdk's approach,但如果两者都是nil,我就不喜欢空字符串。我宁愿拥有nil

func add(a a: String?, b: String?, separator: String = " ") -> String? {
    let results = [a, b].flatMap {$0}
    guard results.count > 0 else { return nil }
    return results.joinWithSeparator(separator)
}

答案 5 :(得分:1)

oisdk回答的很棒,但我需要一些与OP原始问题非常具体的内容。

Swift 4.x ,我创建了这个扩展,在填充其他字符串(例如文本标签)时效果很好。我还更新了它,以便在需要时包含一个处理数组的函数。

extension String {
    static func combine(first: String?, second: String?) -> String {
        return [first, second].compactMap{ $0 }.joined(separator: " ")
    }

    static func combine(strings: [String?]) -> String {
        return strings.compactMap { $0 }.joined(separator: " ")
    }
}

使用两个可选字符串填充文本标签的示例:

print(String.combine(first: "First", second: "Last")) // "First Last"
print(String.combine(first: "First", second: nil)) // "First"
print(String.combine(first: nil, second: "Last")) // "Last"

如果你有一个可选字符串数组,你可以调用数组函数:

print(String.combine(strings: ["I", "Have", nil, "A", "String", nil, "Here"])) 
// "I Have A String Here"

答案 6 :(得分:1)

for swift 4

let name: String? = "Foo"
let surname: String? = "Bar"

let fullname = (name ?? "") + " " + (surname ?? "")

print(fullname)
// Foo Bar

答案 7 :(得分:0)

class cls {

    constructor(options) {

        Object.assign(this, {
            arr: [],
        }, options);

        this.arr[0] = 1; // <- IDE thinks that arr is an unresolved variable
    }
}

答案 8 :(得分:0)

Optional枚举中不再支持运算符是非常糟糕的,但是我像这样重载了标准串联运算符(+):

func +<T: StringProtocol>(lhs: Optional<T>, rhs: Optional<T>) -> String {
    return [lhs, rhs].compactMap({ $0 }).joined()
}

然后您可以像这样使用它:

let first: String? = "first"
let last: String? = nil

first + first // "firstfirst"
first + last // "first"
last + first // "first"
last + last // ""

答案 9 :(得分:0)

附加组件:

考虑你有结构:

struct Person {
   var firstName: String?
   var lastName: String?
}

您可以使用 CustomStringConvertible

extension Person: CustomStringConvertible {

var description: String {
        [firstName, lastName].compactMap { $0 }.joined(separator: " ")
    }
}

 let person1 = Person(firstName "Jeba", lastName: "Moses")
 print(person1) // Prints "Jeba Moses"

let person2 = Person(firstName: "Ebenrick", lastName: nil)
print(person2) // Prints "Ebenrick"