2

I want to replace a series of spaces from a string with an underscore. For example

"This       is     a string with a lot of spaces!"

should become

"This_is_a_string_with_a_lot_of_spaces!"

How to do this?

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
sloeberGJ
  • 355
  • 3
  • 13

4 Answers4

12

Alternative non-regex solution:

let foo = "This       is     a string with a lot of spaces!"
let bar = foo
    .componentsSeparatedByString(" ")
    .filter { !$0.isEmpty }
    .joinWithSeparator("_")

print(bar) /* This_is_a_string_with_a_lot_of_spaces! */

Works also for unicode characters (thanks @MartinR for this beautiful example)

let foo = "       "

// ...

/* _____ */
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • 1
    That's a pretty slick use of Filter. – Nate Birkholz Apr 01 '16 at 18:46
  • 1
    @NateBirkholz I should point out, however, that this method above will not replace groups of spaces prior and after the first and last words, respectively; these spaces will just be removed (e.g. `" This is a string with a lot of spaces! "` will yield the same result as for `"This is a string with a lot of spaces!"`). – dfrib Apr 01 '16 at 18:50
  • That is exactly what I need, so that won't be a problem – sloeberGJ Apr 02 '16 at 12:24
5

@remus suggestion can be simplified (and made Unicode/Emoji/Flag-safe) as

let myString = "  This       is     a string with a lot of spaces!         "
let replacement = myString.stringByReplacingOccurrencesOfString("\\s+", withString: "_", options: .RegularExpressionSearch)
print(replacement)
// _This_is_a_string_with_a_lot_of_spaces!____
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
3

You can use a simple regular expression replacement to do this:

let myString = "     "
if let regex = try? NSRegularExpression(pattern: "\\s+", options: []) {
    let replacement = regex.stringByReplacingMatchesInString(myString, options: .WithTransparentBounds, range: NSMakeRange(0, (myString as NSString).length), withTemplate: "_")
    print(replacement)
    // "_____"
}
brandonscript
  • 68,675
  • 32
  • 163
  • 220
1

Alternative non-regex, pure Swift (no bridging to NSString) solution:

let spaced = "This       is     a string with a lot of spaces!"

let under = spaced.characters.split(" ", allowEmptySlices: false).map(String.init).joinWithSeparator("_")

Alternate, alternate version that doesn't remove leading and trailing spaces when converting. Slightly obfuscated for brevity... ;-)

let reduced = String(spaced.characters.reduce([Character]()) { let n = $1 == " " ? "_" : $1; var o = $0; o.append(n); guard let e = $0.last else { return o }; return e == "_" && n == "_" ? $0 : o })

There's probably a more clever solution involving flatMap() but I'll leave it to someone more clever than I!

  • Just note that as in @dfris' solution, this will remove and not replace initial and trailing spaces. – Martin R Apr 01 '16 at 18:53