1

I have a string like this:

0x829bd824b016326a401d083b33d092293333a830

I want to leave the first 6 characters and leave the last 4:

0x829b...a830

How can I do so? I saw on the Apple docs the option .firstIndex(of: "-") but that would be for removing a specific character, so it doesn't apply.

aheze
  • 24,434
  • 8
  • 68
  • 125
Arturo
  • 3,254
  • 2
  • 22
  • 61
  • 2
    Are you trying to show this in a label or something? In that case you can just let `UILabel` do the work for you: https://stackoverflow.com/questions/20417767/truncate-part-of-text-in-uilabel – aheze Aug 01 '21 at 02:25
  • @aheze I'll be showing it in a SwiftUI view, very likely in a Text("") or label yes, I checked the link you provided but it doesn't seem to apply. The only similar option there is to `NSLineBreakByTruncatingMiddle` but that's just letting it do it for me, I'd like more specific, like leaving the last 4 and some digits at front – Arturo Aug 01 '21 at 02:29

1 Answers1

4

One way you can use drop, like this:

let stringTest: String = "0x829bd824b016326a401d083b33d092293333a830"
    
print(stringTest.replacingOccurrences(of: stringTest.dropFirst(6).dropLast(4), with: "...")) 

// It will print: 0x829b...a830

Here extension:

extension String {
    
    func replacingRange(indexFromStart: Int, indexFromEnd: Int, replacing: String = "") -> Self {
        return self.replacingOccurrences(of: self.dropFirst(indexFromStart).dropLast(indexFromEnd), with: replacing)
    }
    
    func replacingRange2(indexFromStart: Int, indexFromEnd: Int, replacing: String = "") -> Self {
        return String(self.prefix(indexFromStart)) + replacing + String(self.suffix(indexFromEnd))
    }

}

use case:

print(stringTest.replacingRange(indexFromStart: 6, indexFromEnd: 4, replacing: "..."))

The Master Extension from Leo Dabus:

extension StringProtocol where Self: RangeReplaceableCollection {
    
    func replacing<S: StringProtocol>(indexFromStart: Int, indexFromEnd: Int, with string: S = "") -> Self {
        
        Self.init(replacingOccurrences(of: dropFirst(indexFromStart).dropLast(indexFromEnd), with: string))
        
    }
    
    
    func replacing2<S: StringProtocol>(indexFromStart: Int, indexFromEnd: Int, with string: S = "") -> Self {

        Self.init(self.prefix(indexFromStart) + Self(string) + self.suffix(indexFromEnd))
        
    }
    
    func replacing3<S: StringProtocol>(indexFromStart: Int, indexFromEnd: Int, with string: S = "") -> Self {

        Self.init(self.prefix(indexFromStart) + string[...] + self.suffix(indexFromEnd))
        
    }
    
}
ios coder
  • 1
  • 4
  • 31
  • 91
  • no no, I'm trying to keep those, not drop them lol and put some dots `...` in the middle – Arturo Aug 01 '21 at 02:42
  • 2
    @Arturo you can also just do `str.prefix(6) + "..." + str.suffix(4)`. Just make sure the string has enough characters. – Leo Dabus Aug 01 '21 at 03:00
  • 1
    Adding on to @LeoDabus if there's not enough (`let str = "asd"`), the result will be `asd...asd` – aheze Aug 01 '21 at 03:01
  • @aheze that would result in the same string `asd`. It would be the same as replacing an empty string with something else. – Leo Dabus Aug 01 '21 at 03:04
  • @aheze I said to make sure there is enough characters – Leo Dabus Aug 01 '21 at 03:05
  • 1
    @Arturo: I add the extension also. – ios coder Aug 01 '21 at 03:05
  • @swiftPunk as an extension you should extend `StringProtocol` and constrain `Self` to `RangeReplaceableProtocol`. Make the method generic with one generic type to target and another to the replacement string. – Leo Dabus Aug 01 '21 at 03:07
  • @LeoDabus: ok, I am going implement! thanks – ios coder Aug 01 '21 at 03:08
  • @swiftPunk https://stackoverflow.com/questions/24200888/any-way-to-replace-characters-on-swift-string/58436623#58436623 remove the mutating keyword and return Self – Leo Dabus Aug 01 '21 at 03:08
  • 1
    @swiftPunk better to simply use a `ClosedRange` and name it `replacingRange` or maybe `replacingSubrange` – Leo Dabus Aug 01 '21 at 03:10
  • @LeoDabus: please edit my answer in case if it is not finished, I am done with editing. – ios coder Aug 01 '21 at 03:17
  • @swiftPunk I just realized a range wouldn't work because the size of the string is unpredictable – Leo Dabus Aug 01 '21 at 03:19
  • @LeoDabus: I did not planed to catch miss usage of the extension. You know what I mean, I am thinking that developer knows the limits of extension. But we can work on what you said. why not. – ios coder Aug 01 '21 at 03:21
  • @swiftPunk the generic method would look like this `extension StringProtocol where Self: RangeReplaceableCollection {` `func replacing(indexFromStart: Int, indexFromEnd: Int, with string: S = "") -> Self {` `.init(replacingOccurrences(of: dropFirst(indexFromStart).dropLast(indexFromEnd), with: string))` `}` `}` – Leo Dabus Aug 01 '21 at 03:24
  • @LeoDabus: what is this init() you are using? – ios coder Aug 01 '21 at 03:28
  • 1
    This is required to return `Self`. If you would like to return `String` you can remove it. – Leo Dabus Aug 01 '21 at 03:31
  • 1
    It means if you apply this method on a `SubSequence` it will return a `SubSequence`, in this case a `Substring`. Try `let stringTest = "0x829bd824b016326a401d083b33d092293333a830...".dropLast(3)` `let test = stringTest.replacing(indexFromStart: 6, indexFromEnd: 4, with: "...")` – Leo Dabus Aug 01 '21 at 03:33
  • @swiftPunk you can use `Self(`, `.init(` or `Self.init`. I like using `.init(`. Swift is a type inferred language so it will work for any type if it doesn't return an optional. When we are returning the type that conform to that protocol we return `Self` – Leo Dabus Aug 01 '21 at 03:37
  • @LeoDabus: I personally like the `replacing2` – ios coder Aug 01 '21 at 03:43
  • @swiftPunk yes me too. It is native Swift and probably faster. Note that you can also do `string[...]` instead of `Self(string)`. `.init(prefix(indexFromStart) + string[...] + suffix(indexFromEnd))` – Leo Dabus Aug 01 '21 at 03:48
  • @LeoDabus: I made it as `replacing3`, for all who followed until here. to be able seeing the development of code. – ios coder Aug 01 '21 at 04:02
  • @swiftPunk this is called [`UnboundedRange_`](https://developer.apple.com/documentation/swift/unboundedrange-qf8) – Leo Dabus Aug 01 '21 at 04:06
  • @LeoDabus: what? you mean about [...] ? UnboundedRange = [...] ? that was new for me, I must study it in first time I got free time. – ios coder Aug 01 '21 at 04:10