这个问题具体是关于将Character类型的Array转换为String。将字符串数组或数字转换为字符串不是此处讨论的主题。
在以下两行中,我希望将myStringFromArray
设置为" C,a,t!,"
var myChars: [Character] = ["C", "a", "t", "!", ""]
let myStringFromArray = myChars.joinWithSeparator(",");
但是,我无法执行该代码,因为编译器抱怨对成员joinWithSeparator
"的模糊引用。
所以,有两个问题:
1)Apple说," Swift的Character类型的每个实例代表一个扩展 字形集群。扩展的字形簇是一个或一个序列 更多的Unicode标量(组合时)生成单个标量 人类可读的角色。"
对我来说听起来至少是同质的,认为实现joinWithSeparator
方法来支持Character类型是合理的。那么,有没有人有一个很好的答案,为什么他们不这样做?
2)在Swift中将Character类型数组转换为字符串的最佳方法是什么?
注意:如果您不想在字符之间使用分隔符,则解决方案为:
let myStringFromArray = String(myChars)
这会给你" Cat!"
答案 0 :(得分:5)
对我来说,听起来至少是同质的,认为实现joinWithSeparator方法来支持Character类型是合理的。那么,有没有人对他们为什么不这样做有一个很好的答案?
这可能是对设计的疏忽。发生此错误是因为joinWithSeparator(_:)
有两种可能的候选者。我怀疑这种歧义是存在的,因为Swift可以隐含地将双引号解释为String
或Character
。在这种情况下,选择哪一个是模棱两可的。
第一位候选人是joinWithSeparator(_: String) -> String
。它可以满足您的需求。
如果将分隔符视为String
,则会挑选此候选人,结果为:"C,a,t,!,"
第二个是joinWithSeparator<Separator : SequenceType where Separator.Generator.Element == Generator.Element.Generator.Element>(_: Separator) -> JoinSequence<Self>
。它呼叫Sequence
Sequence
,Sequence
作为分隔符。方法签名有点令人满意,所以让我们分解它。此函数的参数是Separator
类型。此Separator
被约束为SequenceType
,其中序列(Seperator.Generator.Element
)的元素必须与此序列序列(Generator.Element.Generator.Element
)的元素具有相同的类型。
复杂约束的关键是确保Sequence
保持同质。例如,您无法将Int
的序列与Double
的序列连接起来。
如果将分隔符视为Character
,则会挑选此候选对象,结果为:["C", ",", "a", ",", "t", ",", "!", ",", ""]
编译器会抛出错误以确保您意识到存在歧义。否则,程序的行为可能与您预期的不同。
您可以通过明确地将每个Character
变为String
来消除这种情况的歧义。由于String
不是SequenceType
,因此不再可能出现#2候选人。
var myChars: [Character] = ["C", "a", "t", "!", ""]
var anotherVar = myChars.map(String.init).joinWithSeparator(",")
print(anotherVar) //C,a,t,!,
答案 1 :(得分:3)
这个答案假设是Swift 2.2。
var myChars: [Character] = ["C", "a", "t", "!", ""]
var myStrings = myChars.map({String($0)})
var result = myStrings.joinWithSeparator(",")
joinWithSeparator
仅适用于String数组:
extension SequenceType where Generator.Element == String {
/// Interpose the `separator` between elements of `self`, then concatenate
/// the result. For example:
///
/// ["foo", "bar", "baz"].joinWithSeparator("-|-") // "foo-|-bar-|-baz"
@warn_unused_result
public func joinWithSeparator(separator: String) -> String
}
您可以创建新的扩展程序以支持字符:
extension SequenceType where Generator.Element == Character {
@warn_unused_result
public func joinWithSeparator(separator: String) -> String {
var str = ""
self.enumerate().forEach({
str.append($1)
if let arr = self as? [Character], endIndex: Int = arr.endIndex {
if $0 < endIndex - 1 {
str.append(Character(separator))
}
}
})
return str
}
}
var myChars: [Character] = ["C", "a", "t", "!", ""]
let charStr = myChars.joinWithSeparator(",") // "C,a,t,!,"
关于Code Review.SE的相关讨论。
答案 2 :(得分:0)
上下文:Swift3(测试版)
TL; DR高飞解决方案
var myChars:[Character] = ["C", "a", "t", "!", ""]
let separators = repeatElement(Character("-"), count: myChars.count)
let zipped = zip(myChars, separators).lazy.flatMap { [$0, $1] }
let joined = String(zipped.dropLast())
<强>博览会强>
行。这让我疯了。部分是因为我陷入了join
语义。连接方法非常有用,但是当你背离它非常具体(但很常见)的字符串连接情况时,它会同时做两件事。它用原始序列拼接其他元素,然后将2个深字符数组(字符串数组)展平为一个单独的数组(字符串)。
OP在阵列中使用单个字符将我的大脑发送到其他地方。上面给出的答案是获得所需内容的最简单方法。将单个字符转换为单个字符串,然后使用join方法。
如果你想分别考虑这两个部分......我们从原始输入开始:
var input:[Character] = ["C", "a", "t", "!", ""]
在我们用分隔符拼接我们的字符之前,我们需要一个分隔符集合。在这种情况下,我们想要一个一次又一次重复的伪集合,而不必实际使用那么多元素创建任何数组:
let separators = repeatElement(Character(","), count: myChars.count)
这将返回一个Repeated
对象(奇怪的是,您无法使用常规init
方法进行实例化。)
现在我们想用分隔符拼接/编织原始输入:
let zipped = zip(myChars, separators).lazy.flatMap { [$0, $1] }
zip
函数返回Zip2Sequence
(奇怪的是必须通过自由函数而不是直接对象引用来实例化)。本身,当枚举时,Zip2Sequence只枚举(eachSequence1, eachSequence2)
的配对元组。 flatMap
表达式将其转换为两个序列中的一系列交替元素。
对于大型输入,这将创建一个较大的中间序列,只是很快就会丢弃。所以我们在那里插入了lazy
访问器,它允许只在需要时计算变换,因为我们正在从中访问元素(想想迭代器)。
最后,我们知道我们可以从任何类型的Character序列中创建一个String。所以我们直接将它传递给String创建。我们添加一个dropLast()以避免添加最后一个逗号。
let joined = String(zipped.dropLast())
以这种方式分解它的有价值的东西(它肯定更多的代码行,所以最好有一个兑换价值),是我们可以深入了解我们可以用来解决类似问题的一些工具join
,但不完全相同。SELECT COUNT(*) as sold_tickets
FROM reservations r left join tickets t
ON t.reservation_id = r.id WHERE date(r.date) = '2016-06-30'
。例如,假设我们想要尾随逗号?加入并不是答案。假设我们想要一个非常量的分隔符?只是重做第二行。等...