How to remove first word from a sentence in swift - ios

I know how to remove first character from a word in swift like this:
var data = "CITY Singapore"
data.removeFirst()
print(data)//ITY Singapore
what i want is to remove the first word and space so the result is "Singapore".
How can i remove the first word and leading space in swift?

You can try
let data = "CITY Singapore"
let res = data.components(separatedBy: " ").dropFirst().joined(separator: " ")
print(res)
Or
let res = data[data.range(of: " ")!.upperBound...] // may crash for no " " inside the string

Or you can go with this too
let strData = "CITY Singapore"
if let data = strData.components(separatedBy: " ").dropFirst().first {
// do with data
}
else {
// fallback
}

This is a Regular Expression solution, the benefit is to modify the string in place.
The pattern searches from the beginning of the string to the first space character
var data = "CITY Singapore"
if let range = data.range(of: "^\\S+\\s", options: .regularExpression) {
data.removeSubrange(range)
}

You can use String's enumerateSubstrings in range method (Foundation) using byWords option and remove the first enclosing range. You need also to stop enumeration after removing the range at the first occurrence:
var string = "CITY Singapore"
string.enumerateSubstrings(in: string.startIndex..., options: .byWords) { (_, _, enclosingRange, stop) in
string.removeSubrange(enclosingRange)
stop = true
}
string // "Singapore"

Related

Remove U\0000fffc unicode scalar from string

I receive an NSAttributedString that contains a NSTextAttachment. I want to remove that attachment, and it looks like it is represented as "\u{ef}" in the string. Printing the unicode scalars of such string, it also seems that unicode scalar for the "\u{ef}" is U\0000fffc.
I tried to do this:
noAttachmentsText = text.replacingOccurrences(of: "\u{ef}", with: "")
with no success, so I'm trying by comparing unicode scalars:
var scalars = Array(text.unicodeScalars)
for scalar in scalars {
// compare `scalar` to `U\0000fffc`
}
but I'm not able either to succeed in the comparison.
How could I do this?
But this code works for me from How do I remove "\U0000fffc" from a string in Swift?
let original = "First part \u{ef} Last part"
let originalRange = Range<String.Index>(start: original.startIndex, end: original.endIndex)
let target = original.stringByReplacingOccurrencesOfString("\u{ef}", withString: "", options: NSStringCompareOptions.LiteralSearch, range: originalRange)
print(target)
Output :
"First part ï Last part"
to
First part Last part
U can use similar code for swift 3 just replace unicode using replacingOccurrences option for exapmle :
func stringTocleanup(str: String) -> String {
var result = str
result = result.replacingOccurrences(of: "\"", with: "\"")
.replacingOccurrences(of: "\u{10}", with: "")
return result
}

Syntax-highlighting Text With a Custom List of Keywords

I'm working on a macOS application. I need to syntax-highlight text that is placed over TextView (NSTextView) with a list of selected words. For simplicity, I'm actually testing the same feature on the iPhone Simulator. Anyway, a list of words to highlight comes as a form of an array. The following is what I have.
func HighlightText {
let tagArray = ["let","var","case"]
let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
style.alignment = NSTextAlignment.Left
let words = textView.string!.componentsSeparatedByString(" ") // textView.text (UITextView) or textView.string (NSTextView)
let attStr = NSMutableAttributedString()
for i in 0..<words.count {
let word = words[i]
if HasElements.containsElements(tagArray,text: word,ignore: true) {
let attr = [
NSForegroundColorAttributeName: syntaxcolor,
NSParagraphStyleAttributeName: style,
]
let str = (i != words.count-1) ? NSAttributedString(string: word.stringByAppendingString(" "), attributes: attr) : NSAttributedString(string: word, attributes: attr)
attStr.appendAttributedString(str)
} else {
let attr = [
NSForegroundColorAttributeName: NSColor.blackColor(),
NSParagraphStyleAttributeName: style,
]
let str = (i != words.count-1) ? NSAttributedString(string: word.stringByAppendingString(" "), attributes: attr) : NSAttributedString(string: word, attributes: attr)
attStr.appendAttributedString(str)
}
}
textView.textStorage?.setAttributedString(attStr)
}
class HasElements {
static func containsElements(array:Array<String>,text:String,ignore:Bool) -> Bool {
var has = false
for str in array {
if str == text {
has = true
}
}
return has
}
}
The simple methodology here is to separate the entire string of text into words with a white space (" ") and puts each word in an array (words). The containsElements function simply tells whether or not the selected word contains one of the keywords in the array (tagArray). If it returns true, the word is put in an NSMutableAttributedString with a highlight color. Otherwise, it's put in the same attributed string with a plain color.
The problem with this simple methodology is that a separated word puts the last word and /n and the next word together. For example, if I have a string like
let base = 3
let power = 10
var answer = 1
, only the first 'let' will be highlighted as the code puts 3 and the next let together like '3\nlet.' If I separate any word containing \n with a fast enumeration, the code won't detect each new paragraph well. I appreciate any advice to make it better. Just FYI, I'm going to leave this topic open to both macOS and iOS.
Muchos thankos
Couple different options. String has a function called componentsSeparatedByCharactersInSet that allows you to separate by a character set you define. Unfortunately this won't work since you want to separate by \n which is more than one character.
You could split the words twice.
let firstSplit = textView.text!.componentsSeparatedByString(" ")
var words = [String]()
for word in firstSplit {
let secondSplit = word.componentsSeparatedByString("\n")
words.appendContentsOf(secondSplit)
}
But then you wouldn't have any sense of the line breaks.. You'd need to re add them back in.
Finally, the easiest hack is simply:
let newString = textView.text!.stringByReplacingOccurrencesOfString("\n", withString: "\n ")
let words = newString.componentsSeparatedByString(" ")
So basically you add your own spaces.

regex to get "words" delimited by space(s)?

What would the regex be (to be used in IOS, "NSRegularExpression") to get the "words" from a string delimited by a space(s), i.e. could be " ", or " ", or " " etc as the delimited.
So therefore:
"26:43:33 S 153:02:51 E"
Would give:
1-"26:43:33"
2-"S"
3-"153:02:51"
4-"E"
So therefore:
"26:43:33 S 153:02:51 E"
Would give:
1-"26:43:33"
2-"S"
3-"153:02:51"
4-"E"
So if you're going to use a regex for this, you want to look for all contiguous stretches of not-space. Like this:
let s = "26:43:33 S 153:02:51 E" as NSString
let pattern = "[^ ]+"
let reg = try! NSRegularExpression(pattern: pattern, options: [])
let matches = reg.matchesInString(s as String, options: [], range: NSMakeRange(0, s.length))
let result = matches.map {s.substringWithRange($0.range)}
// result is: ["26:43:33", "S", "153:02:51", "E"]
As an alternative to regex, I would suggest using the split method on your string.
let string = "26:43:33 S 153:02:51 E"
let words = string.characters.split { $0 == " " }.map { String($0) }
Because calling split on the characters property will return an array of Character types, we need to use the map method to convert them back to strings. map will perform a closure on each element of a collection. In this case we just use it to cast each element to a String

Return range with first and last character in string

I have a string: "Hey #username that's funny". For a given string, how can I search the string to return all ranges of string with first character # and last character to get the username?
I suppose I can get all indexes of # and for each, get the substringToIndex of the next space character, but wondering if there's an easier way.
If your username can contain only letters and numbers, you can use regular expression for that:
let s = "Hey #username123 that's funny"
if let r = s.rangeOfString("#\\w+", options: NSStringCompareOptions.RegularExpressionSearch) {
let name = s.substringWithRange(r) // #username123"
}
#Vladimir's answer is correct, but if you're trying to find multiple occurrences of "username", this should also work:
let s = "Hey #username123 that's funny"
let ranges: [NSRange]
do {
// Create the regular expression.
let regex = try NSRegularExpression(pattern: "#\\w+", options: [])
// Use the regular expression to get an array of NSTextCheckingResult.
// Use map to extract the range from each result.
ranges = regex.matchesInString(s, options: [], range: NSMakeRange(0, s.characters.count)).map {$0.range}
}
catch {
// There was a problem creating the regular expression
ranges = []
}
for range in ranges {
print((s as NSString).substringWithRange(range))
}

Extract a whole word from string In Swift

for example I have a String text like : "I have to go to the kitchen"
and If I searched this text using the 'av' phrase I want a way that return me the whole word 'have'
how I can do this in swift
There is very nice solution with filter in swift.You can use rangeOfString method of String with filter to get only filtered string having "av"
var s = "I have to go to the kitchen"
//will return "have"
let abc:[String] = s.componentsSeparatedByString(" ").filter({ $0.rangeOfString("av", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil, locale: nil) != nil } )
There is an API for that, enumerateSubstrings(in:options:using:)
The byWords option returns all words in the closure
let string = "I have to go to the kitchen"
var found : String?
string.enumerateSubstrings(in: string.startIndex..., options: .byWords) { substring, _, _, stop in
if let word = substring, word.contains("av") {
found = word
stop = true
}
}
print(found ?? "not found")
Split your string into array by space char (" "), and return component that contains your 'av' string.
let words = stringYouWantToSearchIn.componentsSeparatedByString(" ")
for word in words
{
var range = word.rangeOfString(lastWord)
if (range != nil)
{
//you got what do you want in 'word variable'
break
}
}

Resources