Below is my "services" variable. I want to remove first 2 characters from it. That is I want to replace ", " with ""
let services = ", EXTERNAL SERVICE, INTERNAL SERVICE"
I want to produce following result
let services = "EXTERNAL SERVICE, INTERNAL SERVICE"
How to do it?
If you always want to remove the first two characters, use String.substring(from:).
let services = ", EXTERNAL SERVICE, INTERNAL SERVICE"
let correctServices = services.substring(from: services.index(services.startIndex, offsetBy: 2))
Output: "EXTERNAL SERVICE, INTERNAL SERVICE"
This is a solution based on the assumption that the string is composed with string concatenation from an array or loop separated by ", ".
It converts the string to array, removes the empty item(s) and converts the string back to string
let services = ", EXTERNAL SERVICE, INTERNAL SERVICE"
.components(separatedBy: ", ")
.filter{ !$0.isEmpty }
.joined(separator: ", ")
I guess the best solution is not to compose services by string concatenation before.
It looks like you want to get rid of extraneous characters from the beginning, and maybe from the end. In your case you have two characters, but there is a more general way - which is trimming. This is from a playground
// Your original string
let string = ", EXTERNAL SERVICE, INTERNAL SERVICE"
// Create a character set for things to exclude - in this case whitespace, newlines and punctuation
let charset = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
// Trimming removes the characters from the characterset from the beginning and the end of the string
let trimmedString = string.trimmingCharacters(in: charset) // -> "EXTERNAL SERVICE, INTERNAL SERVICE"
Related
I am currently trying to setup a string to be added to a HTTP POST request where a user would type text and tap 'enter' and a request would be sent.
I know multiple characters (^,+,<,>) can be replaced with a single character ('_') like so:
userText.replacingOccurrences(of: "[^+<>]", with: "_"
I currently am using multiple functions of:
.replacingOccurrences(of: StringProtocol, with:StringProtocol)
like so:
let addAddress = userText.replacingOccurrences(of: " ", with: "_").replacingOccurrences(of: ".", with: "%2E").replacingOccurrences(of: "-", with: "%2D").replacingOccurrences(of: "(", with: "%28").replacingOccurrences(of: ")", with: "%29").replacingOccurrences(of: ",", with: "%2C").replacingOccurrences(of: "&", with: "%26")
Is there a more efficient way of doing this?
What you are doing is to manually encode the string with a percent encoding.
If that's the case, this will help you:
addingPercentEncoding(withAllowedCharacters:)
Returns a new string made from the receiver by replacing all characters not in the specified set with percent-encoded characters.
https://developer.apple.com/documentation/foundation/nsstring/1411946-addingpercentencoding
For your specific case this should work:
userText.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
I think the only problem you will run into with using addingPercentEncoding is that your question states that a space " " should be replaced with an underscore. Using addingPercentEncoding for a space " " will return %20. You should be able to combine some of these answers, define the remaining characters from your list that should return standard character replacement and get your desired outcome.
var userText = "This has.lots-of(symbols),&stuff"
userText = userText.replacingOccurrences(of: " ", with: "_")
let allowedCharacterSet = (CharacterSet(charactersIn: ".-(),&").inverted)
var newText = userText.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet)
print(newText!) // Returns This_has%2Elots%2Dof%28symbols%29%2C%26stuff
Ideally to use .urlHostAllowed CharacterSet since it works almost always.
textInput.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
But the best is combining all the possible options like here which will make sure you make it right.
I have a string and substring(http) and I want to replace that substring but I don't know when that substring will end. I mean want to check it until one space is not coming and after that I want to replace it.
I am checking that if my string contains http which is also a string then I want to replace it when space will come.
Here below is my example :-
let string = "Hello.World everything is good http://www.google.com By the way its good".
This is my string It can be dynamic also I mean in this above string http is there, so I want to replace "http://www.google.com" to "website".
So it would be
string = "Hello.World everything is good website By the way its good"
A possible solution is Regular Expression
The pattern searches for http:// or https:// followed one or more non-whitespace characters up to a word boundary.
let string = "Hello.World everything is good http://www.google.com By the way its good"
let trimmedString = string.replacingOccurrences(of: "https?://\\S+\\b", with: "website", options: .regularExpression)
print(trimmedString)
Split each words, replace and join back should solve this.
// split into array
let arr = string.components(separatedBy: " ")
// do checking and join
let newStr = arr.map { word in
return word.hasPrefix("http") ? "website" : word
}.joined(separator: " ")
print(newStr)
this might be a basic question but I am having a hard time not including the - in the second
var title1 = "I will be part of string 1 - I am part of string 2"
let end = title1.range(of: "-", options: .backwards)?.lowerBound
let firstPartRange = title1.startIndex..<end!
var secondPart = title1.substring(with: firstPartRange) // Gives me "I will be part of string 1" which is correct
title1.substring(from: end!) // however this guy gives me "- I am part of string 2" & I only want to get "I am part of string 2" without the space and dash in front
Can I shift the range or change it's lowerBound somehow?. I know I can user separate component by function here but would like to learn how to offset my range
You just need to get the index after end or offset it by 2. Note that you should also make sure it doesn't pass the end index using the method index(theIndex, offsetBy: n, limitedBy: endIndex)
let title1 = "I will be part of string 1 - I am part of string 2"
if let end = title1.range(of: "-", options: .backwards)?.lowerBound {
let firstPartRange = title1.startIndex..<end
let secondPart = title1.substring(with: firstPartRange) // "I will be part of string 1 "
title1.substring(from: title1.index(after: end)) // " I am part of string 2"
// or to offset it by two you should also make sure it doesn't pass the end index
title1.substring(from: title1.index(end, offsetBy: 2, limitedBy: title1.endIndex) ?? title1.endIndex) // "I am part of string 2"
}
You are looking for index(_:offsetBy:). This is a method of the original string, like this:
var title1 = "I will be part of string 1 - I am part of string 2"
let end = title1.range(of: "-", options: .backwards)!.lowerBound
let ix = title1.index(end, offsetBy: 2)
title1.substring(from: ix) // "I am part of string 2"
You can separate the contents of string by using components(separatedBy: String) method which will return you with array of separated strings then you can remove white spaces from the last element.
var title1 = "I will be part of string 1 - I am part of string 2"
print(title1.components(separatedBy: "-").last!.trimmingCharacters(in: .whitespacesAndNewlines))
it will give you the desired result
"I am part of string 2"
Hope it helps!
You could use the components function and include the spaces in the separator:
title1.components(separatedBy:" - ")
As #matt suggest, you are looking for index(_:offsetBy:)
A little bit different approach using Swift standard library only (no Foundation)
let str = "I will be part of string 1 - I am part of string 2"
let parts = str.characters.split(separator: "-").map(String.init)
if you would like to trim all extra spaces
let partsTrimmed = parts.map {
$0.characters.split(separator: " ").map(String.init).joined(separator: " ")
}
import Foundation
for i in 1 ... n {
let entry = readLine()!.characters.split(" ").map(String.init)
let name = entry[0]
let phone = Int(entry[1])!
phoneBook[name] = phone``
}
//can someone explain this piece of code`
I assume you know everything else in the code except this line:
let entry = readLine()!.characters.split(" ").map(String.init)
readLine() reads user input and returns it. Let's say the user input is
Sweeper 12345678
using .characters.split(" "), we split the input using a separator. What is this separator? A space (" ")! Now the input has been split into two - "Sweeper" and "12345678".
We want the two split parts to be strings, right? Strings are much more easier to manipulate. Currently the split parts are stored in an array of String.CharacterView.SubSequence. We want to turn each String.CharacterView.SubSequence into a string. That is why we use map. map applies a certain function to everything in a collection. So
.map(String.init)
is like
// this is for demonstration purposes only, not real code
for x in readLine()!.characters.split(" ") {
String.init(x)
}
We have now transformed the whole collection into strings!
There is error in your code replace it like below:
let entry = readLine()!.characters.split(separator: " ").map(String.init)
Alternative to the above code is:
let entry = readLine()!.components(separatedBy: " ")
Example:
var str = "Hello, playground"
let entry = str.characters.split(separator: " ").map(String.init)
print(entry)
Now characters.split with split the characters with the separator you give in above case " "(space). So it will generate an array of characters. And you need to use it as string so you are mapping characters into String type by map().
So I have function that strips off a trailing ", " (comma + space) at the end of a string and I'm getting the above error even though I'm ensuring that the string is not empty. The following code:
print("stripping trailing commas")
for var detail in details {
if detail.contains(",") {
print(detail)
detail.remove(at: detail.endIndex) // <-- Removes last space
detail.remove(at: detail.endIndex) // <-- Removes last comma
}
}
...results int the following console output:
stripping trailing commas
2016,
fatal error: Can't form a Character from an empty String
The first instance detail.remove(at: detail.endIndex) is being highlighted by the debugger, and while I can't be sure the space is present from the console message, I'm adding ", " at the end of each entry in a list so any string that actually contains a comma should not only have characters (as the console indicates) but it should have an extra two chars at the end that need to be stripped.
Thanks in advance, for any help on what's causing the error and how to resolve?
Try change
detail.remove(at: detail.endIndex)
to
detail.remove(at: detail.index(before: detail.endIndex))
A simple way to do this without using import Foundation (needed for contains()) or calculating indexes would be something like this:
let details = ["one, two, three, ", "a, b", "once, twice, thrice, so nice, ", ""]
let filtered = details.map { (original: String) -> String in
guard original.hasSuffix(", ") else { return original }
return String(original.characters.dropLast(2))
}
print(filtered) // -> "["one, two, three", "a, b", "once, twice, thrice, so nice", ""]\n"
This won't remove any empty strings that are in the returned array. If you need that functionality it can easily be added.