3

I'm using swift in my project. I want to change a specific range of string with a character. for example I have a string "1234567890" and I want to change characters in range, location 5 and length 3 to "". the out put should be "12345***90".

I see a ways for doing this by converting string to NSString and using this function:

stringByReplacingCharactersInRange

but is there any better way? a swift way :)

2 Answers 2

2

There's a way to write that in Swift in one line:

let stringA = "1234567890" let stringB = String(stringA.enumerated().map { !(5...7).contains($0) ? $1 : "*" }) let stringC = String(stringA.enumerated().compactMap { !(5...7).contains($0) ? $1 : $0 == 5 ? "*" : nil }) print(stringB) // "12345***90\n" print(stringC) // "12345*90\n" 

Just to add some explanation: We enumarate the String so we can use the indexes to map the Characters based on their position on the String. On the closure, $0 corresponds to the offset and $1 to the Character on the iteration. It could also be written as $0.offset and $0.element, respectively.
On the second example with stringC, where it replaces with only one *, we replace the Character in position 5 with the * and the rest with nil, and the compactMap will return all of the non-nil results.

Sign up to request clarification or add additional context in comments.

4 Comments

what should I do if I want to replace range 5...7 with single "*" character?
this can also be written as (5...7).contains($0) ? "*" : $1
@behrad compactMap { !(5...7).contains($0) ? $1 : 5 == $0 ? "*" : nil }
@behrad I've updated the answer considering the comments and added some explanations, hope it's all clear.
1

Maybe this?

var myString = "1234567890" let startIndex = myString.index(myString.startIndex, offsetBy: 5) let endIndex = myString.index(startIndex, offsetBy: 3) myString.replaceSubrange(startIndex..<endIndex, with: "***") print("\(myString)") 

Write an extension if necessary

extension String { mutating func replaceSubString(startAt: Int, offsetBy: Int, with newString: String) { let startIndex = self.index(self.startIndex, offsetBy: startAt) let endIndex = self.index(startIndex, offsetBy: offsetBy) self.replaceSubrange(startIndex..<endIndex, with: newString) } } 

and you use it like this:

var myString = "1234567890" myString.replaceSubString(startAt: 5, offsetBy: 3, with: "***") print("\(myString)") 

3 Comments

Better to extend StringProtocol and constrain Self to RangeReplaceableCollectiom to support substrings as well
And add the non mutating counterpart as well replacingSubrange. I would also rename the method to replaceSubrange
And you don't need to return anything on a mutating method

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.