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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.