Search for exact match in string based on values in array - arrays

I am trying to search for items in an array using a free text string. I have got so far, see code below, but I'm still returning results which only partially match.
var townArray = ["Leamington Spa", "Birmingham", "Coventry", "Leamington Hastings", "Royal Leamington Spa", "Lea", "Leam", "Cove"]
let searchText = "Anyone want to meet in Leamington Spa or Coventry"
var resultsArray = [String]()
for i in townArray {
let range = searchText.lowercased().range(of: i.lowercased(), options: .regularExpression)
// (8 times)
if range != nil {
let found = searchText.substring(with: range!)
print(found)
resultsArray.append(found)
// (5 times)}
}
print(resultsArray)
// ["Leamington Spa", "Coventry", "Lea", "Leam", "Cove"]

Exact word matching is not a simple thing, you may need to use regular expression.
For example:
var townArray = ["Leamington Spa", "Birmingham", "Coventry", "Leamington Hastings", "Royal Leamington Spa", "Lea", "Leam", "Cove"]
let searchText = "Anyone want to meet in Leamington Spa or Coventry"
let townRegexArray = townArray.map {townName -> (name: String, regex: NSRegularExpression) in
let pattern = townName.components(separatedBy: " ")
.map{"\\b"+NSRegularExpression.escapedPattern(for: $0)+"\\b"}
.joined(separator: "\\s+")
//print(pattern) //->\bLeamington\b\s+\bSpa\b (=="\\bLeamington\\b\\s+\\bSpa\\b")...
let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)
return (name: townName, regex: regex)
}
let resultsArray = townRegexArray
.filter{$0.regex.firstMatch(in: searchText, range: NSRange(0..<searchText.utf16.count)) != nil}
.map{$0.name}
print(resultsArray) //->["Leamington Spa", "Coventry"]
\b ("\\b" in String literal) represents word boundary in regex. So \bLeam\b does not match to Leamington.

You would do something like this
let matchingStrings = resultsArray.filter { $0 == "TARGET_STRING" }
let containsString = !matchingStrings.isEmpty

Related

Need to get certain words from a long string swift

So I have a this long text string and I need to get the words that are in the { } so I can put these in an array.
This is the string: <p style=\"text-align:center\">There will be some text here.<br><br>Send More Text in here<br><br>${LogoSquare} ${WUSquare} ${VisaSquare}</p>"
I have a regEx to see when I've reach the words that I need:
static let regEX = "^.*\\b(LogoSquare|WUSquare|VisaSquare)\\b.*$"
With the following function
fun containsValues(text: String) -> Bool {
if let regex = try? NSRegularExpression(pattern: AdviceCardRegexPattern.mytd, options: [.dotMatchesLineSeparators]) {
return (regex.firstMatch(in: text, options: [], range: NSRange(location: 0, length: text.count)) != nil)
}
return false
}
This is what I've tried so far:
var components = textPayload.components(separatedBy: ">")
I do the above so that the values get separated from the last > so it becomes like this
"${LogoSquare} ${WUSquare} ${VisaSquare}</p", ""]
Then I have:
let removal: [Character] = ["$", "{", "}", "<", "/"]
var imageTags: [String] = []
for value in components {
if containsValues(text: value) {
imageTags.append(value.filter { !removal.contains($0)})
}
}
This prints the following:
["LogoSquare WUSquare VisaSquarep"]
The only thing that's left is getting rid of the p at the end of VisaSquare
You're over-thinking this. Just match against ${something} and capture the something. For instance:
let s = "hey nonny nonny ${LogoSquare} ${WUSquare} ${VisaSquare} yoho yo"
let r = try! NSRegularExpression(pattern: "\\$\\{(.*?)\\}")
var result = [String]()
let ss = s as NSString
for m in r.matches(in: s, options: [], range: NSMakeRange(0, ss.length)) {
result.append(ss.substring(with: m.range(at: 1)))
}
print(result)

Detect if string contains any element of a string array

How would I detect if a string contains any member of an array of strings (words)?
Here is the array:
let str:String = "house near the beach"
let wordGroups:[String] = ["beach","waterfront","with a water view","near ocean","close to water"]
The following is not compiling
let match:Bool = wordGroups.contains(where: str.contains)
I am using String extension:
extension String {
func contains(_ strings: [String]) -> Bool {
strings.contains { contains($0) }
}
}
Use case:
let str = "house near the beach"
let wordGroups = ["beach","waterfront", "with a water view", "near ocean", "close to water"]
let haveWord = str.contains(wordGroups)
In additional to answer of #Sh_Khan, if you want match some word from group:
let str:String = "house near the beach"
let wordGroups:[String] = ["beach","waterfront","with a water view","near ocean","close to water"]
let worlds = wordGroups.flatMap { $0.components(separatedBy: " ")}
let match = worlds.filter { str.range(of:$0) != nil }.count != 0
You can try
let str = Set("house near the beach")
let match = wordGroups.filter { str.contains($0) }.count != 0

Regular Expression Check: return boolean and answers

(Make it short to help others)
check if a string matches to a regex:
text.range(of: regex, options: .regularExpression) == nil
check string selected part matches:
let nsString = self as NSString
let regex = try NSRegularExpression(pattern: pattern)
let allMatches = regex
.matches(in: self, options: [], range: NSRange(location: 0, length: nsString.length))
return allMatches.map { match in
return (1 ..< match.numberOfRanges)
.map { matchIndex in
return nsString.substring(with: match.range(at: matchIndex))
}
}
The first one is easy and we don't actually need NSRegularExpression for that:
extension String {
func hasMatches(_ pattern: String) -> Bool {
return self.range(of: pattern, options: .regularExpression) != nil
}
}
let regex = "(.*) [:] (.*)"
let string = "Tom : how are you?"
print(string.hasMatches(regex))
I would say that we don't even need a utility function for that.
The second is harder to understand, mostly because NSRegularExpression API is not really converted to Swift and it even uses old NSString:
extension String {
func getMatches(_ pattern: String) throws -> [[String]] {
let nsString = self as NSString
let expression = try NSRegularExpression(pattern: pattern)
let matches = expression
.matches(in: self, options: [], range: NSRange(location: 0, length: nsString.length))
return matches.map { match in
let numGroups = match.numberOfRanges
// we are skipping group 0 which contains the pattern itself
return (1 ..< numGroups)
.map { groupIndex in
return nsString.substring(with: match.range(at: groupIndex))
}
}
}
}
print(try! string.getMatches(regex)) // [["Tom", "how are you?"]]
Note that I am returning an array of arrays because the expression can match multiple times.
For example:
let regex = "(\\d+):(\\d+)"
let string = "01:23, 02:34"
print(try! string.getMatches(regex)) // [["01", "23"], ["02", "34"]]

how to change my String Value into Array by removing "()"

Let say I have values like this
Apple(100)
Orange(300)
Pineapple(10)
Grape(50)
Banana(1000)
What I want to do is to create an array which was like that to each string
["Apple","100"]
["Orange","300"]
What i tried was like that,but it doesn't meet my answer well enough
var myNewFruits = "Apple(200)"
var newStr = myNewFruits.componentsSeparatedByString("(")
The Output was
["Apple","200)"]
What i really want was
["Apple","200"]
Is there any help with Swift?Thank you.Because I am creating search with that,so,i really need it.
You can use a custom NSCharacterSet and get the first two elements from the returned array:
let myNewFruits = "Apple(200)"
let newStr = myNewFruits.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "()"))[0...1] // ["Apple", "200"]
You can do it this way:
func stringToArr(str: String) -> [String] {
var newArr = [String]()
var fullNameArr = split(str) {$0 == "("}
newArr.append(fullNameArr[0])
var last: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil
newArr.append(last!.stringByReplacingOccurrencesOfString(")", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil))
return newArr
}
var string = "Apple(100)" //"Apple(100)"
let newArr = stringToArr(string) //["Apple", "100"]

Check if array contains part of a string in Swift?

I have an array containing a number of strings. I have used contains() (see below) to check if a certain string exists in the array however I would like to check if part of a string is in the array?
itemsArray = ["Google, Goodbye, Go, Hello"]
searchToSearch = "go"
if contains(itemsArray, stringToSearch) {
NSLog("Term Exists")
}
else {
NSLog("Can't find term")
}
The above code simply checks if a value is present within the array in its entirety however I would like to find "Google, Google and Go"
Try like this.
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
let searchToSearch = "go"
let filteredStrings = itemsArray.filter({(item: String) -> Bool in
var stringMatch = item.lowercaseString.rangeOfString(searchToSearch.lowercaseString)
return stringMatch != nil ? true : false
})
filteredStrings will contain the list of strings having matched sub strings.
In Swift Array struct provides filter method, which will filter a provided array based on filtering text criteria.
First of all, you have defined an array with a single string.
What you probably want is
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
Then you can use contains(array, predicate) and rangeOfString() – optionally with
.CaseInsensitiveSearch – to check each string in the array
if it contains the search string:
let itemExists = contains(itemsArray) {
$0.rangeOfString(searchToSearch, options: .CaseInsensitiveSearch) != nil
}
println(itemExists) // true
Or, if you want an array with the matching items instead of a yes/no
result:
let matchingTerms = filter(itemsArray) {
$0.rangeOfString(searchToSearch, options: .CaseInsensitiveSearch) != nil
}
println(matchingTerms) // [Google, Goodbye, Go]
Update for Swift 3:
let itemExists = itemsArray.contains(where: {
$0.range(of: searchToSearch, options: .caseInsensitive) != nil
})
print(itemExists)
let matchingTerms = itemsArray.filter({
$0.range(of: searchToSearch, options: .caseInsensitive) != nil
})
print(matchingTerms)
Try like this.
Swift 3.0
import UIKit
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
var filterdItemsArray = [String]()
func filterContentForSearchText(searchText: String) {
filterdItemsArray = itemsArray.filter { item in
return item.lowercased().contains(searchText.lowercased())
}
}
filterContentForSearchText(searchText: "Go")
print(filterdItemsArray)
Output
["Google", "Goodbye", "Go"]
In Swift 5 with better readability :
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
let searchString = "Googled"
let result = itemsArray.contains(where: searchString.contains)
print(result) //prints true in the above case.
MARK:- Swift 5, Swift 4
//MARK:- You will find the array when its filter in "filteredStrings" variable you can check it by count if count > 0 its means you have find the results
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
let searchToSearch = "go"
let filteredStrings = itemsArray.filter({(item: String) -> Bool in
let stringMatch = item.lowercased().range(of: searchToSearch.lowercased())
return stringMatch != nil ? true : false
})
print(filteredStrings)
if (filteredStrings as NSArray).count > 0
{
//Record found
//MARK:- You can also print the result and can do any kind of work with them
}
else
{
//Record Not found
}
func filterContentForSearchText(_ searchText: String) {
filteredString = itemsArray.filter({( item : String) -> Bool in
return item.lowercased().contains(searchText.lowercased())
})
}
In Swift 4:
let itemsArray = ["Google", "Goodbye", "Go", "Hello"]
let searchString = "Go"
let filterArray = itemsArray.filter({ { $0.range(of: searchString, options: .caseInsensitive) != nil}
})
print(filterArray)
I had the same problem recently, didn't like most of these answers,
solved it like this:
let keywords = ["doctor", "hospital"] //your array
func keywordsContain(text: String) -> Bool { // text: your search text
return keywords.contains { (key) -> Bool in
key.lowercased().contains(text.lowercased())
}
}
This will also correctly trigger searches like "doc", which many of the above answers do not and is best practice.
contains() is more performant than first() != nil
source: https://www.avanderlee.com/swift/performance-collections/
If you are just checking if an item exists in a specific array, try this:
var a = [1,2,3,4,5]
if a.contains(4) {
print("Yes, it does contain number 4")
}
else {
print("No, it doesn't")
}

Resources