Getting specific range of characters from a string swift 3 - ios

i would like to get specific characters from my string, like this for example
var str = "hey steve #steve123, you would love this!"
// Without doing this
var theCharactersIWantFromTheString = "#steve123"
How would i just retrieve the #steve123 from str

You can use regular expression "\\B\\#\\w+".
let pattern = "\\B\\#\\w+"
let sentence = "hey steve #steve123, you would love this!"
if let range = sentence.range(of: pattern, options: .regularExpression) {
print(sentence.substring(with: range)) // "#steve123\n"
}

Related

Swift regex format to remove string contains brackets in iOS

Need to remove part of the string based on brackets.
For ex:
let str = "My Account (_1234)"
I wanted to remove inside brackets (_1234) and the result should be string My Account
Expected Output:
My Account
How can we achieve this with regex format or else using swift default class,need support on this.
Tried with separatedBy but it splits string into array but that is not the expected output.
str.components(separatedBy: "(")
Use replacingOccurrences(…)
let result = str.replacingOccurrences(of: #"\(.*\)"#,
with: "",
options: .regularExpression)
.trimmingCharacters(in: .whitespaces))
Regex ist not necessary. Just get the range of ( and extract the substring up to the lower bound of the range
let str = "My Account (_1234)"
if let range = str.range(of: " (") {
let account = String(str[..<range.lowerBound])
print(account)
}

In Swift, how can I detect an "emoji tag"? [duplicate]

This question already has answers here:
Find out if Character in String is emoji?
(17 answers)
Closed 6 years ago.
func getEmojiTags(text: String) -> [String] {
}
An emoji tag is a combination of two parts, with no spaces between them. If there is a space between them, then it is not an emojiTag.
a character which is an emoji
a string which is not an emoji
For example:
Hello, my name is Jason 😀 🐸 how are you ?-> []
Hello, my name is 😀Jason -> [😀Jason]
Hello, my name is 😀 Jason -> []
I am going to the ⛱beach with some 🙉monkeys 👏 -> [⛱beach, 🙉monkeys]
Try using NSRegularExpression with emoji code ranges.
func emojiTags(str: String) -> [String] {
//A little bit simplified, you may need to define what are your "emoji".
//This is a subset defined in http://stackoverflow.com/a/36258684/6541007 .
let emojiCharacters = "\\U0001F600-\\U0001F64F\\U0001F300-\\U0001F5FF\\U0001F680-\\U0001F6FF\\u2600-\\u26FF"
let pattern = "[\(emojiCharacters)][^\(emojiCharacters)\\s]+"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matchesInString(str, options: [], range: NSRange(0..<str.utf16.count))
return matches.map{(str as NSString).substringWithRange($0.range)}
}
let str1 = "Hello, my name is Jason 😀 🐸 how are you ?"
print(emojiTags(str1)) //->[]
let str2 = "Hello, my name is 😀Jason"
print(emojiTags(str2)) //->["😀Jason"]
let str3 = "Hello, my name is 😀 Jason"
print(emojiTags(str3)) //->[]
let str4 = "I am going to the ⛱beach with some 🙉monkeys 👏"
print(emojiTags(str4)) //->["⛱beach", "🙉monkeys"]

How to take NSRange in swift?

I am very much new to swift language. I am performing some business logic which needs to take NSRange from given String.
Here is my requirement,
Given Amount = "144.44"
Need NSRange of only cent part i.e. after "."
Is there any API available for doing this?
You can do a regex-based search to find the range:
let str : NSString = "123.45"
let rng : NSRange = str.range("(?<=[.])\\d*$", options: .RegularExpressionSearch)
Regular expression "(?<=[.])\\d*$" means "zero or more digits following a dot character '.' via look-behind, all the way to the end of the string $."
If you want a substring from a given string you can use componentsSeparatedByString
Example :
var number: String = "144.44";
var numberresult= number.componentsSeparatedByString(".")
then you can get components as :
var num1: String = numberresult [0]
var num2: String = numberresult [1]
hope it help !!
Use rangeOfString and substringFromIndex:
let string = "123.45"
if let index = string.rangeOfString(".") {
let cents = string.substringFromIndex(index.endIndex)
print("\(cents)")
}
Another version that uses Swift Ranges, rather than NSRange
Define the function that returns an optional Range:
func centsRangeFromString(str: String) -> Range<String.Index>? {
let characters = str.characters
guard let dotIndex = characters.indexOf(".") else { return nil }
return Range(dotIndex.successor() ..< characters.endIndex)
}
Which you can test with:
let r = centsRangeFromString(str)
// I don't recommend force unwrapping here, but this is just an example.
let cents = str.substringWithRange(r!)

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))
}

componentsseparatedbystring by multiple separators in Swift

So here is the string s:
"Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."
I want them to be separated to a array as:
["Hi", "How are you", "I'm fine", "It is 6 p.m", "Thank you", "That's it"]
Which means the separators should be ". " + "? " + "! "
I've tried:
let charSet = NSCharacterSet(charactersInString: ".?!")
let array = s.componentsSeparatedByCharactersInSet(charSet)
But it will separate p.m. to two elements too. Result:
["Hi", " How are you", " I'm fine", " It is 6 p", "m", " Thank you", " That's it"]
I've also tried
let array = s.componentsSeparatedByString(". ")
It works well for separating ". " but if I also want to separate "? ", "! ", it become messy.
So any way I can do it? Thanks!
There is a method provided that lets you enumerate a string. You can do so by words or sentences or other options. No need for regular expressions.
let s = "Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."
var sentences = [String]()
s.enumerateSubstringsInRange(s.startIndex..<s.endIndex, options: .BySentences) {
substring, substringRange, enclosingRange, stop in
sentences.append(substring!)
}
print(sentences)
The result is:
["Hi! ", "How are you? ", "I\'m fine. ", "It is 6 p.m. ", "Thank you! ", "That\'s it."]
rmaddy's answer is correct (+1). A Swift 3 implementation is:
var sentences = [String]()
string.enumerateSubstrings(in: string.startIndex ..< string.endIndex, options: .bySentences) { substring, substringRange, enclosingRange, stop in
sentences.append(substring!)
}
You can also use regular expression, NSRegularExpression, though it's much hairier than rmaddy's .bySentences solution. In Swift 3:
var sentences = [String]()
let regex = try! NSRegularExpression(pattern: "(^|\\s+)(\\w.*?[.!?]+)(?=(\\s+|$))")
regex.enumerateMatches(in: string, range: NSMakeRange(0, string.characters.count)) { match, flags, stop in
sentences.append((string as NSString).substring(with: match!.rangeAt(2)))
}
Or Swift 2:
let regex = try! NSRegularExpression(pattern: "(^|\\s+)(\\w.*?[.!?]+)(?=(\\s+|$))", options: [])
var sentences = [String]()
regex.enumerateMatchesInString(string, options: [], range: NSMakeRange(0, string.characters.count)) { match, flags, stop in
sentences.append((string as NSString).substringWithRange(match!.rangeAtIndex(2)))
}
The [.!?] syntax matches any of those three characters. The | means "or". The ^ matches the start of the string. The $ matches the end of the string. The \\s matches a whitespace character. The \\w matches a "word" character. The * matches zero or more of the preceding character. The + matches one or more of the preceding character. The (?=) is a look-ahead assertion (e.g. see if there's something there, but don't advance through that match).
I've tried to simplify this a bit, and it's still pretty complicated. Regular expressions offer rich text pattern matching, but, admittedly, it is a little dense when you first use it. But this rendition matches (a) repeated punctuation (e.g. "Thank you!!!"), (b) leading spaces, and (c) trailing spaces, too.
If the splitting basis is something a little more esoteric than sentences, this extension could work.
extension String {
public func components(separatedBy separators: [String]) -> [String] {
var output: [String] = [self]
for separator in separators {
output = output.flatMap { $0.components(separatedBy: separator) }
}
return output.map { $0.trimmingCharacters(in: .whitespaces)}
}
}
let artists = "Rihanna, featuring Calvin Harris".components(separated by: [", with", ", featuring"])
I tried to find a regex to solve this too: (([^.!?]+\s)*\S+(\.|!|\?))
Here the explanation from regexper and an example
Well I've found a regex too from here
var pattern = "(?<=[.?!;…])\\s+(?=[\\p{Lu}\\p{N}])"
let s = "Hi! How are you? I'm fine. It is 6 p.m. Thank you! That's it."
let sReplaced = s.stringByReplacingOccurrencesOfString(pattern, withString:"[*-SENTENCE-*]" as String, options:NSStringCompareOptions.RegularExpressionSearch, range:nil)
let array = sReplaced.componentsSeparatedByString("[*-SENTENCE-*]")
Perhaps it's not a good way as it has to first replace and than separate the string. :)
UPDATE:
For regex part, if you also want to match Chinese/Japanese punctuations (which space after each punctuation is not necessary), you can use the following one:
((?<=[.?!;…])\\s+|(?<=[。!?;…])\\s*)(?=[\\p{L}\\p{N}])

Resources