Swift:String.join()如何处理自定义类型?

Swift:String.join()如何处理自定义类型?,swift,Swift,例如: var a = [1, 2, 3] // Ints var s = ",".join(a) // EXC_BAD_ACCESS 是否可以使连接函数返回“1,2,3” 扩展Int(或其他自定义类型)以符合某些协议?试试这个 var a = [1, 2, 3] // Ints var s = ",".join(a.map { $0.description }) 或添加此扩展名 extension String { func join<S : SequenceT

例如:

var a = [1, 2, 3]    // Ints
var s = ",".join(a)  // EXC_BAD_ACCESS
是否可以使连接函数返回“1,2,3”

扩展Int(或其他自定义类型)以符合某些协议?

试试这个

var a = [1, 2, 3]    // Ints
var s = ",".join(a.map { $0.description })
或添加此扩展名

extension String {
    func join<S : SequenceType where S.Generator.Element : Printable>(elements: S) -> String {
        return self.join(map(elements){ $0.description })
    }

  // use this if you don't want it constrain to Printable
  //func join<S : SequenceType>(elements: S) -> String {
  //    return self.join(map(elements){ "\($0)" })
  //}
}

var a = [1, 2, 3]    // Ints
var s = ",".join(a)  // works with new overload of join
扩展字符串{
func连接(元素:S)->字符串{
返回self.join(映射(元素){$0.description})
}
//如果不希望将其约束为可打印,请使用此选项
//func连接(元素:S)->字符串{
//返回self.join(映射(元素){“\($0)”})
//}
}
变量a=[1,2,3]//整数
var s=“,”.join(a)//用于join的新重载

联接定义为

extension String {
    func join<S : SequenceType where String == String>(elements: S) -> String
}
扩展字符串{
func连接(元素:S)->字符串
}

这意味着它需要一个字符串序列,您不能将int序列传递给它。

即使您不能使join对自定义类型起作用,也有一个简单的解决方法。 您所要做的就是在类(或扩展内置类)上定义一个方法以返回字符串,然后将其映射到联接中

例如,我们可以:

extension Int {
    func toString() -> String {
        return "\(self)" // trivial example here, but yours could be more complex
    }
然后你可以做:

let xs = [1, 2, 3]
let s = join(xs.map { $0.toString() })
我不建议为此使用
.description
,因为默认情况下它将调用
.debugDescription
,这在生产代码中并不特别有用


在任何情况下,最好提供一个显式方法来转换为适合连接的字符串,而不是依赖于一个通用的“描述”方法,您可能会在以后更改该方法。

最简单的方法是@BryanChen答案的变体:

",".join(a.map { String($0) } )

Swift 2中的Xcode 7.0 beta 6开始,现在您应该使用
[String].joinWithSeparator(“,”)

在您的例子中,仍然需要将Int更改为String类型,因此我添加了
map()

Swift 3中的Xcode 8.0 beta 1代码略微更改为
[String]。已加入(分隔符:“,”)


为了使您的生活更加完整,从Swift 3中的Xcode 8.0 beta 1开始,您现在应该使用
[String].joined(分隔符:“,”

这是Swift API的新“ed/ing”命名规则:

根据其副作用命名功能和方法

  • 那些没有副作用的应该读作名词短语,例如x.distance(to:y),i.继任者()
  • 有副作用的应该读作祈使动词短语,例如print(x),x.sort(),x.append(y)
  • 名称突变/非突变方法对一致。突变方法通常会有一个语义相似的非突变变量,但它会返回一个新值,而不是就地更新实例。
快速解决方案

public extension Sequence where Iterator.Element: CustomStringConvertible {
    func joined(seperator: String) -> String {
        return self.map({ (val) -> String in
            "\(val)"
        }).joined(separator: seperator)
    }
}

debugDescription
用于调试,而不是
description
@BryanChen这是真的,但值得注意的是后者的
NSObject
实现调用了前者。我将编辑我的帖子以澄清。这比使用结果不能保证的
description
要好
String()
保证生成
String
@Zaph“结果不保证”是什么意思?
description
字段用于提供人类可读的描述。对于
Int
,通常是将数字转换为字符串表示形式。但是作为一个(计算的)属性,它可以被重写,尽管对于
Int
@Antonio,这种情况不太可能发生,我仍然不明白。
字符串(1)
是否保证其值?如果您重写(您不能为
Int
description
,您可能是指它(尽管这是一个坏主意)字符串(1)保证生成包含“1”的字符串。现在
Int.description
返回“1”,但可能明天苹果决定将其实现更改为返回“(Int)1”或其他内容<代码>说明用于提供对象的字符串说明,而不是将对象转换为字符串。这就是说,如果您仍然使用
说明
,那么它现在就可以工作了。明天可能不会如你所期望的那样。我不喜欢第二个未发表评论的建议。它似乎不够健壮或通用。依靠这样的描述似乎是错误的。另外,注释选项(使用($0))在IMO中并不令人惊讶。它在使用“join”操作时打开了到字符串的隐式转换。用户甚至不知道它发生了。在我看来,简单地使用就地映射更为冗长,也更具可读性。
var s3 = a.map { String($0) }.joined(separator: ",")    // "1,2,3"
public extension Sequence where Iterator.Element: CustomStringConvertible {
    func joined(seperator: String) -> String {
        return self.map({ (val) -> String in
            "\(val)"
        }).joined(separator: seperator)
    }
}