This question already has answers here:
Detect whole word in NSStrings
(4 answers)
Closed 6 years ago.
What I want to do is to check if an entire word is present in a string. Let me give you an example.
let mainString = "this is a my string"
let searchString = "str"
if mainString.containsString(searchString) {
}
Here this condition will be true but I do not want this. I want it to be true when either "this" or "is" or "a" or "my" or "string" is searched in the mainString meaning I want to compare the whole word not the characters within the string. I hope I have elaborated it.
// The following method will return a string without punctuation and non-required stuff characters
Source of information : How to remove special characters from string in Swift 2?
func removeSpecialCharsFromString(mainString) -> String {
let okayChars : Set<Character> =
Set("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)
return String(text.characters.filter {okayChars.contains($0) })
}
let stringWithoutSpecialChars = removeSpecialCharsFromString(mainString)
// Source of info : Chris's answer on this page
let components = stringWithoutSpecialChars.componentsSeparatedByString(" ")
for component in components {
print(component)
}
You have to use a Regex like that :
NSString *pattern = #"\\str\\b";
NSRange range = [text rangeOfString:pattern options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
The \b at the end of the pattern do what you want, it will match only whole words.
I would recommend splitting your string into components and seeing if a component matches your string. Below is a method that uses components to check if any word matches a given search term.
func isTermInString(term:String, stringToSearch:String) -> Bool {
let components = stringToSearch.componentsSeparatedByString(" ")
for component in components {
if component == term {
return true
}
}
return false
}
Related
This question already has answers here:
Swift Regex for extracting words between parenthesis
(2 answers)
Closed 4 years ago.
Example String -
exampleString ( 123 )
I want two parts from the above string -
1-) exampleString by splitting
2-) 123 by splitting and then removing brackets and two spaces, one at each end
More specifically, I want to know how can I extract a string between
two brackets ( )
How to achieve that in swift 4.2?
Thanks
There is a solution below, it will extract any string between brackets into an array without brackets, it also gives you string without element as word as an array element:
var myString = "exampleString ( 123 ) "
//creates result array from String by separating elements by space
var result = myString.split(separator: " ")
//filters array to remove '(' and ')'
result = result.filter { $0 != "(" && $0 != ")" }
print(result)
Then if you want to build a String back from result array with string elements, do the following:
var resultString = result.joined(separator: " ")
print(resultString)
Might not be ideal, but it might be useful for you.
I found this beautiful String Extension for slicing a string. It is answered here -
Slice String Extension
extension String {
func slice(from: String, to: String) -> String? {
return (range(of: from)?.upperBound).flatMap { substringFrom in
(range(of: to, range: substringFrom..<endIndex)?.lowerBound).map { substringTo in
String(self[substringFrom..<substringTo])
}
}
}
}
Here I can simply get a substring like
let str = "exampleString ( 123 )"
print(str.slice(from: "( ", to: " )"))
This question already has answers here:
How to remove special characters from string in Swift 2?
(6 answers)
Closed 3 years ago.
I need to filter invisible character from a string. In the attached screen shot, string "Cilantro" has some hidden character and when i get count of this before and after removing hidden character it shows different character count.
I just want to filter invisible characters not special characters, for example I dont want to filter á, ã è etc characters.
Note: I removed hidden characters using "delete" button.
For the reference I am adding here the String with invisible character: "Cilantro". I am not sure if it will show at your end too.
Swift 5 or later
You can use new Character isLetter property
let del = Character(UnicodeScalar(127)!)
let string = "Cilantro\(del)\(del)"
print(string.count) // "10\n"
let filtered = string.filter { $0.isLetter }
print(filtered.count) // "8\n"
let string = "cafe\u{301}"
let filtered = string.filter { $0.isLetter }
print(filtered) // "café"
If you just want to remove zero width spaces from your string you can do as follow:
extension Character {
static let zeroWidthSpace = Self(.init(0x200B)!)
var isZeroWidthSpace: Bool { self == .zeroWidthSpace }
}
extension Bool {
var negated: Bool { !self }
}
let str = "Cilantro"
print(str.count) // 9
let filtered = str.filter(\.isZeroWidthSpace.negated)
print(filtered.count) // 8
This question already has answers here:
Finding index of character in Swift String
(33 answers)
Closed 6 years ago.
This sounds easy, but I am stumped. The syntax and functions of Range are very confusing to me.
I have a URL like this:
https://github.com/shakked/Command-for-Instagram/blob/master/Analytics%20Pro.md#global-best-time-to-post
I need to extract the part #global-best-time-to-post, essentially the # to the end of the string.
urlString.rangeOfString("#") returns Range
Then I tried doing this assuming that calling advanceBy(100) would just go to the end of the string but instead it crashes.
hashtag = urlString.substringWithRange(range.startIndex...range.endIndex.advancedBy(100))
Easiest and best way to do this is use NSURL, I included how to do it with split and rangeOfString:
import Foundation
let urlString = "https://github.com/shakked/Command-for-Instagram/blob/master/Analytics%20Pro.md#global-best-time-to-post"
// using NSURL - best option since it validates the URL
if let url = NSURL(string: urlString),
fragment = url.fragment {
print(fragment)
}
// output: "global-best-time-to-post"
// using split - pure Swift, no Foundation necessary
let split = urlString.characters.split("#")
if split.count > 1,
let fragment = split.last {
print(String(fragment))
}
// output: "global-best-time-to-post"
// using rangeofString - asked in the question
if let endOctothorpe = urlString.rangeOfString("#")?.endIndex {
// Note that I use the index of the end of the found Range
// and the index of the end of the urlString to form the
// Range of my string
let fragment = urlString[endOctothorpe..<urlString.endIndex]
print(fragment)
}
// output: "global-best-time-to-post"
You could also use substringFromIndex
let string = "https://github.com..."
if let range = string.rangeOfString("#") {
let substring = string.substringFromIndex(range.endIndex)
}
but I'd prefer the NSURL way.
use componentsSeparatedByString method
let url = "https://github.com/shakked/Command-for-Instagram/blob/master/Analytics%20Pro.md#global-best-time-to-post"
let splitArray = url.componentsSeparatedByString("#")
your required last text phrase (without # char) will be at the last index of the splitArray , you can concatenate the # with your phrase
var myPhrase = "#\(splitArray[splitArray.count-1])"
print(myPhrase)
This question already has answers here:
Formatting a UITextField for credit card input like (xxxx xxxx xxxx xxxx)
(30 answers)
Closed 6 years ago.
I've been stuck on this for awhile now and I was wondering what is the best way to format a textfield for a credit card type format?
You can use Caishen framework.
It updates the contents of the textfield after every edit using this function :
public func formattedCardNumber(cardNumberString: String) -> String {
let regex: NSRegularExpression
let cardType = cardTypeRegister.cardTypeForNumber(Number(rawValue: cardNumberString))
do {
let groups = cardType.numberGrouping
var pattern = ""
var first = true
for group in groups {
pattern += "(\\d{1,\(group)})"
if !first {
pattern += "?"
}
first = false
}
regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions())
} catch {
fatalError("Error when creating regular expression: \(error)")
}
return NSArray(array: self.splitString(cardNumberString, withRegex: regex)).componentsJoinedByString(self.separator)
}
I have a Swift based iOS app and one of the features allows you to comment on a post. Anyway, users can add "#mentions" in their posts to tag other people. However I want to stop the user from adding a username with a capital letter.
Is there anyway I can convert a string, so that the #usernames are all in lowercase?
For example:
I really enjoy sightseeing with #uSerABC (not allowed)
I really enjoy sightseeing with #userabc (allowed)
I know there is a property for the string in swift called .lowercaseString - but the problem with that, is that it makes the entire string lowercase and thats not what I want. I only want the #username to be in lower case.
Is there any way around this with having to use the .lowercase property.
Thanks for your time, Dan.
This comes from a code I use to detect hashtags, I've modified to detect mentions:
func detectMentionsInText(text: String) -> [NSRange]? {
let mentionsDetector = try? NSRegularExpression(pattern: "#(\\w+)", options: NSRegularExpressionOptions.CaseInsensitive)
let results = mentionsDetector?.matchesInString(text, options: NSMatchingOptions.WithoutAnchoringBounds, range: NSMakeRange(0, text.utf16.count)).map { $0 }
return results?.map{$0.rangeAtIndex(0)}
}
It detects all the mentions in a string by using a regex and returns an NSRange array, by using a range you have the beginning and the end of the "mention" and you can easily replace them with a lower case version.
Split the string into two using the following command -
let arr = myString.componentsSeparatedByString("#")
//Convert arr[1] to lower case
//Append to arr[0]
//Enjoy
Thanks to everyone for their help. In the end I couldn't get any of the solutions to work and after a lot of testing, I came up with this solution:
func correctStringWithUsernames(inputString: String, completion: (correctString: String) -> Void) {
// Create the final string and get all
// the seperate strings from the data.
var finalString: String!
var commentSegments: NSArray!
commentSegments = inputString.componentsSeparatedByString(" ")
if (commentSegments.count > 0) {
for (var loop = 0; loop < commentSegments.count; loop++) {
// Check the username to ensure that there
// are no capital letters in the string.
let currentString = commentSegments[loop] as! String
let capitalLetterRegEx = ".*[A-Z]+.*"
let textData = NSPredicate(format:"SELF MATCHES %#", capitalLetterRegEx)
let capitalResult = textData.evaluateWithObject(currentString)
// Check if the current loop string
// is a #user mention string or not.
if (currentString.containsString("#")) {
// If we are in the first loop then set the
// string otherwise concatenate the string.
if (loop == 0) {
if (capitalResult == true) {
// The username contains capital letters
// so change it to a lower case version.
finalString = currentString.lowercaseString
}
else {
// The username does not contain capital letters.
finalString = currentString
}
}
else {
if (capitalResult == true) {
// The username contains capital letters
// so change it to a lower case version.
finalString = "\(finalString) \(currentString.lowercaseString)"
}
else {
// The username does not contain capital letters.
finalString = "\(finalString) \(currentString)"
}
}
}
else {
// The current string is NOT a #user mention
// so simply set or concatenate the finalString.
if (loop == 0) {
finalString = currentString
}
else {
finalString = "\(finalString) \(currentString)"
}
}
}
}
else {
// No issues pass back the string.
finalString = inputString
}
// Pass back the correct username string.
completion(correctString: finalString)
}
Its certainly not the most elegant or efficient solution around but it does work. If there are any ways of improving it, please leave a comment.