如何用多步空格分隔字符串中的字符?
How to separate characters in String by whitespace with multiple strides?
我有一个工作函数,它用白色分隔每个 n 个字符space,效果很好。
这是代码 (Swift 5):
extension String {
/// Creates a new string, separating characters specified by stride lenght.
/// - Parameters:
/// - stride: Desired stride lenght.
/// - separator: Character to be placed in between separations
func separate(every stride: Int, with separator: Character) -> String {
return String(self.enumerated().map { [=10=] > 0 && [=10=] % stride == 0 ? [separator, ] : [] }.joined())
}
}
这会像这样打印 1234123412341234 的示例字符串
1234 1234 1234 1234
现在,我如何将这个字符串 1234123412341234 分隔成多个步幅,例如白色 space 设置在第 4 个字符之后,然后是第 6 个字符之后,然后是第 5 个字符之后,如下所示:
1234 123412 34123 4
以下是我的做法:
// Prints sequences of bools using 1/0s for easy reading
func p<S: Sequence>(_ bools: S) where S.Element == Bool {
print(bools.map { [=10=] ? "1" : "0"}.joined())
}
// E.g. makeWindow(span: 3) returns 0001
func makeWindow(span: Int) -> UnfoldSequence<Bool, Int> {
return sequence(state: span) { state in
state -= 1
switch state {
case -1: return nil
case 0: return true
case _: return false
}
}
}
// E.g. calculateSpacePositions(spans: [4, 6, 5]) returns 000100000100001
func calculateSpacePositions<S: Sequence>(spans: S)
-> LazySequence<FlattenSequence<LazyMapSequence<S, UnfoldSequence<Bool, Int>>>>
where S.Element == Int {
return spans.lazy.flatMap(makeWindow(span:))
}
extension String {
func insertingSpaces(at spans: [Int]) -> String {
let spacePositions = calculateSpacePositions(spans: spans + [Int.max])
// p(spacePositions.prefix(self.count))
let characters = zip(inputString, spacePositions)
.flatMap { character, shouldHaveSpace -> [Character] in
return shouldHaveSpace ? [character, "_"] : [character]
}
return String(characters)
}
}
let inputString = "1234123412341234"
let result = inputString.insertingSpaces(at: [4, 6, 5])
print(result)
主要思想是我想要 zip(self, spacePositions)
,这样我就可以获得 self
的字符序列,以及一个告诉我是否应该附加 [=44] 的布尔值=] 在当前字符之后。
为了计算 spacePositions
,我首先创建了一个函数,当给定一个 Int
输入 span
时,会 return span
false
s 后跟 true
。例如。 makeWindow(span: 3)
return 是一个产生 false, false, false, true
.
的序列
从那里开始,只需为输入的每个元素制作其中一个 windows,然后使用 flatMap
将它们全部连接在一起。我懒惰地做这一切,所以我们实际上不需要存储所有这些重复的布尔值。
虽然我遇到了一个障碍。如果你输入[4, 6, 5]
,我习惯的输出是4
个字符,space,6
个字符,space,5
字符, 结束.字符串的其余部分丢失了,因为 zip
产生的序列长度等于两个输入中较短输入的长度。
为了解决这个问题,我在 spans
输入上附加了 Int.max
。这样,space 个位置就是 000010000001000001 ...now followed by Int.max falses
.
func separate(text: String,every stride: [Int], with separator: Character)->String {
var separatorLastPosition = 0 // This is the last separator position in text
var myText = text
if text.count < stride.reduce(0,+){
return text //if your text length not enough for adding separator for all stride positions it will return the text without modifications.you can return error msg also
}else{
for (index, item) in stride.enumerated(){
myText.insert(separator, at:myText.index(myText.startIndex, offsetBy: index == 0 ? item : separatorLastPosition+item))
separatorLastPosition += item+1
}
return myText
}
}
print(separate(text: "12345678901234567890", every: [2,4,5,2], with: " "))
//Result -- 12 3456 78901 23 4567890
func separateCharcters(numbers: String, every: inout [Int], character: Character) ->String{
var counter = 0
var numbersWithSpaces = ""
for (_, number) in numbers.enumerated(){
numbersWithSpaces.append(number)
if !every.isEmpty{
counter += 1
if counter == every.first!{
numbersWithSpaces.append(character)
every.removeFirst()
counter = 0
}
}
}
return numbersWithSpaces
}
Test Case
var numberArray = [4, 6, 5]
separateCharcters(numbers: "1234123412341234", every: &numberArray, character: " ")
Return Result = "1234 123412 34123 4"
我有一个工作函数,它用白色分隔每个 n 个字符space,效果很好。
这是代码 (Swift 5):
extension String {
/// Creates a new string, separating characters specified by stride lenght.
/// - Parameters:
/// - stride: Desired stride lenght.
/// - separator: Character to be placed in between separations
func separate(every stride: Int, with separator: Character) -> String {
return String(self.enumerated().map { [=10=] > 0 && [=10=] % stride == 0 ? [separator, ] : [] }.joined())
}
}
这会像这样打印 1234123412341234 的示例字符串
1234 1234 1234 1234
现在,我如何将这个字符串 1234123412341234 分隔成多个步幅,例如白色 space 设置在第 4 个字符之后,然后是第 6 个字符之后,然后是第 5 个字符之后,如下所示:
1234 123412 34123 4
以下是我的做法:
// Prints sequences of bools using 1/0s for easy reading
func p<S: Sequence>(_ bools: S) where S.Element == Bool {
print(bools.map { [=10=] ? "1" : "0"}.joined())
}
// E.g. makeWindow(span: 3) returns 0001
func makeWindow(span: Int) -> UnfoldSequence<Bool, Int> {
return sequence(state: span) { state in
state -= 1
switch state {
case -1: return nil
case 0: return true
case _: return false
}
}
}
// E.g. calculateSpacePositions(spans: [4, 6, 5]) returns 000100000100001
func calculateSpacePositions<S: Sequence>(spans: S)
-> LazySequence<FlattenSequence<LazyMapSequence<S, UnfoldSequence<Bool, Int>>>>
where S.Element == Int {
return spans.lazy.flatMap(makeWindow(span:))
}
extension String {
func insertingSpaces(at spans: [Int]) -> String {
let spacePositions = calculateSpacePositions(spans: spans + [Int.max])
// p(spacePositions.prefix(self.count))
let characters = zip(inputString, spacePositions)
.flatMap { character, shouldHaveSpace -> [Character] in
return shouldHaveSpace ? [character, "_"] : [character]
}
return String(characters)
}
}
let inputString = "1234123412341234"
let result = inputString.insertingSpaces(at: [4, 6, 5])
print(result)
主要思想是我想要 zip(self, spacePositions)
,这样我就可以获得 self
的字符序列,以及一个告诉我是否应该附加 [=44] 的布尔值=] 在当前字符之后。
为了计算 spacePositions
,我首先创建了一个函数,当给定一个 Int
输入 span
时,会 return span
false
s 后跟 true
。例如。 makeWindow(span: 3)
return 是一个产生 false, false, false, true
.
从那里开始,只需为输入的每个元素制作其中一个 windows,然后使用 flatMap
将它们全部连接在一起。我懒惰地做这一切,所以我们实际上不需要存储所有这些重复的布尔值。
虽然我遇到了一个障碍。如果你输入[4, 6, 5]
,我习惯的输出是4
个字符,space,6
个字符,space,5
字符, 结束.字符串的其余部分丢失了,因为 zip
产生的序列长度等于两个输入中较短输入的长度。
为了解决这个问题,我在 spans
输入上附加了 Int.max
。这样,space 个位置就是 000010000001000001 ...now followed by Int.max falses
.
func separate(text: String,every stride: [Int], with separator: Character)->String {
var separatorLastPosition = 0 // This is the last separator position in text
var myText = text
if text.count < stride.reduce(0,+){
return text //if your text length not enough for adding separator for all stride positions it will return the text without modifications.you can return error msg also
}else{
for (index, item) in stride.enumerated(){
myText.insert(separator, at:myText.index(myText.startIndex, offsetBy: index == 0 ? item : separatorLastPosition+item))
separatorLastPosition += item+1
}
return myText
}
}
print(separate(text: "12345678901234567890", every: [2,4,5,2], with: " "))
//Result -- 12 3456 78901 23 4567890
func separateCharcters(numbers: String, every: inout [Int], character: Character) ->String{
var counter = 0
var numbersWithSpaces = ""
for (_, number) in numbers.enumerated(){
numbersWithSpaces.append(number)
if !every.isEmpty{
counter += 1
if counter == every.first!{
numbersWithSpaces.append(character)
every.removeFirst()
counter = 0
}
}
}
return numbersWithSpaces
}
Test Case
var numberArray = [4, 6, 5]
separateCharcters(numbers: "1234123412341234", every: &numberArray, character: " ")
Return Result = "1234 123412 34123 4"