I know there is an build in method to get the index of substring from the original string by using rangeOfString. But it is used to get the first occurrence of a given substring. However what I need to do is to get the last occurrence of the given substring.
This is something like the rindex in python language
So, my question is, How can I do that in Swift 2.x/3? A code snippet example is appreciated.
You are close. Try the below, adding the optional options parameter and searching the string from the back instead.
let myString = "testingteststring"
let lastSubstringRange = myString.range(of: "test", options: String.CompareOptions.backwards)
'lastSubstringRange' will be the range of the last 'test' substring in 'myString'.
For more info, try looking at Apple Developer: https://developer.apple.com/reference/swift/string/1642786-range
Related
By looking an introductory tutorial on how to use SQLite in Swift (in the iOS context), I saw the following line of code:
let queryString = "INSERT INTO Heroes (name, powerrank) VALUES (?,?)"
tutorial URL : https://www.simplifiedios.net/swift-sqlite-tutorial/
I don't understand if this is a Swift feature of something which will be parsed by SQL
It it some kind of string interpolation, like:
var s = "The value is \(value)"
Or is it something else?
This other tutorial sheds some light regarding the meaning of said syntax:
https://www.raywenderlich.com/6620276-sqlite-with-swift-tutorial-getting-started
It says:
Here, you define a value for the ? placeholder. The function’s name — sqlite3_bind_int() — implies you’re binding an Int to the statement.
The first parameter of the function is the statement to bind to, while the second is a non-zero-based index for the position of the ? you’re binding to. The third and final parameter is the value itself. This binding call returns a status code, but for now, you assume that it succeeds.
I have very limited experience with regex, and never used it for this type of situation, so I'm hoping someone can lead me in the right direction.
I get a link returned from a web service that will look something like this:
<a id="inventoryID-123456789" class="inventory item">See update</a>
What I need to do is create a regex that will get me back the digits in inventoryID. It will always be between 8 & 12 digits and followed by a 'class' tag.
This is using swift 4.2.
I appreciate any help.
If you are receiving a html tag and you want to get the id attribute which always has "inventoryID-<numeric id>" syntax, you could use the following pattern:
\w+-\d+
Have you tried some library for html tag parsing? It could help a lot too.
The easiest way to find an 8-12 digit numeric string is
let link = "<a id=\"inventoryID-123456789\" class=\"inventory item\">See update</a>"
if let range = link.range(of: "\\d{8,12}", options: .regularExpression) {
let inventoryID = String(link[range])
print(inventoryID)
}
I have two arrays of strings and I want to check if a string of array a matches a string from array b. Those strings are phone numbers that might come in different formats. For example:
Array a might have a phone number with prefix like so +44123123123 or 0044123123123
Array b have a standard format without prefixes like so 123123123
So I'm looking for a regex that can match a part of a string like +44123123123 with 123123123
Btw I'm using Swift but I don't think there's a native way to do it (at least a more straightforward solution)
EDIT
I decided to reactivate the question after experimenting with the library #Larme mentioned because of inconsistent results.
I'd prefer a simper solution as I've stated earlier.
SOLUTION
Thanks guys for the responses. I saw many comments saying that Regex is not the right solution for this problem. And this is partly true. It could be true (or false) depending on my current setup/architecture ( which thinking about it now I realise that I should've explained better).
So I ended up using the native solution (hasSuffix/contains) but to do that I had to do some refactoring on the way the entire flow was structured. In the end I think it was the least complicated solution and more performant of the two. I'll give the bounty to #Alexey Inkin for being the first to mention the native solution and the right answer to #Ωmega for providing a more complete solution.
I believe regex is not the right approach for this task.
Instead, you should do something like this:
var c : [String] = b.filter ({ (short : String) -> Bool in
var result = false
for full in a {
result = result || full.hasSuffix(short)
}
return result
})
Check this demo.
...or similar solution like this:
var c : [String] = b.filter ({ (short : String) -> Bool in
for full in a {
if full.hasSuffix(short) { return true }
}
return false
})
Check this demo.
As you do not mention requirements to prefixes, the simplest solution is to check if string in a ends with a string in b. For this, take a look at https://developer.apple.com/documentation/swift/string/1541149-hassuffix
Then, if you have to check if the prefix belongs to a country, you may replace ^00 with + and then run a whitelist check against known prefixes. And the prefix itself can be obtained as a substring by cutting b's length of characters. Not really a regex's job.
I agree with Alexey Inkin that this can also nicely be solved without regex. If you really want a regex, you can try something like the following:
(?:(\+|00)(93|355|213|1684|376))?(\d+)
^^^^^^^^^^^^^^^^^^^^^ Add here all your expected country prefixes (see below)
^^^ ^^ Match a country prefix if it exists but don't give it a group number
^^^^^^^ Match the "prefix-prefix" (+ or 00)
^^^^ Match the local phone number
Unfortunatly with this regex, you have to provide all the expected country prefixes. But you can surely get this list online, e.g. here: https://www.countrycode.org
With this regex above you will get the local phone number in matching group 3 (and the "prefix-prefix" in group 1 and the country code in group 2).
If I have a number that is over 1,000, so that it has a comma in it, how can I either strip out the commas, or convert this number into a Double, so that I can run mathematical operations on it?
Right now, I have the following code:
let oldBFTally: Double = Double(plBFTally.text!)!
let newBFTally: Double = round(1000 * (rawValue + oldBFTally) / 1000)
This code works great, as long as the number is under 1000. But, being that I am formatting the number as text, so that it has commas (ie: 1,234.56), whenever I try to run that first line, it errors out, saying: "fatal error: unexpectedly found nil while unwrapping an Optional value".
Any ideas what I can do to navigate around this issue?
But, being that I am formatting the number as text, so that it has commas (ie: 1,234.56)
You're trying to tackle the problem in the wrong way. If you're generating this string in the first place, then if you want to perform mathematical operations on the number, you shouldn't be displaying it as a string in the UI, then trying to go backwards from the UI back to a number. That's misusing your presentation layer as your data model.
Instead of trying to go back and forth between the UI, use the original value you generated the string from.
#Jim is correct; your text field should simply contain a textual representation of your internal variable, so you shouldn't need to convert back to a double, but for reference, you can use a NumberFormatter
import Foundation
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
if let number = formattter.number(from:"10,000") {
print(number.doubleValue)
}
I've research this topic extensibly and I'm asking as a last resort before assuming that there is no wildcard for what I want to do.
I need to pull up all the text input elements from the document and add it to an array. However, I only want to add the input elements that have an id.
I know you can use the \S* wildcard when using an id selector such as $(#\S*), however I can't use this because I need to filter the results by text type only as well, so I searching by attribute.
I currently have this:
values_inputs = $("input[type='text'][id^='a']");
This works how I want it to but it brings back only the text input elements that start with an 'a'. I want to get all the text input elements with an 'id' of anything.
I can't use:
values_inputs = $("input[type='text'][id^='']"); //or
values_inputs = $("input[type='text'][id^='*']"); //or
values_inputs = $("input[type='text'][id^='\\S*']"); //or
values_inputs = $("input[type='text'][id^=\\S*]");
//I either get no values returned or a syntax error for these
I guess I'm just looking for the equivalent of * in SQL for JQuery attribute selectors.
Is there no such thing, or am I just approaching this problem the wrong way?
Actually, it's quite simple:
var values_inputs = $("input[type=text][id]");
Your logic is a bit ambiguous. I believe you don't want elements with any id, but rather elements where id does not equal an empty string. Use this.
values_inputs = $("input[type='text']")
.filter(function() {
return this.id != '';
});
Try changing your selector to:
$("input[type='text'][id]")
I figured out another way to use wild cards very simply. This helped me a lot so I thought I'd share it.
You can use attribute wildcards in the selectors in the following way to emulate the use of '*'. Let's say you have dynamically generated form in which elements are created with the same naming convention except for dynamically changing digits representing the index:
id='part_x_name' //where x represents a digit
If you want to retrieve only the text input ones that have certain parts of the id name and element type you can do the following:
var inputs = $("input[type='text'][id^='part_'][id$='_name']");
and voila, it will retrieve all the text input elements that have "part_" in the beginning of the id string and "_name" at the end of the string. If you have something like
id='part_x_name_y' // again x and y representing digits
you could do:
var inputs = $("input[type='text'][id^='part_'][id*='_name_']"); //the *= operator means that it will retrieve this part of the string from anywhere where it appears in the string.
Depending on what the names of other id's are it may start to get a little trickier if other element id's have similar naming conventions in your document. You may have to get a little more creative in specifying your wildcards. In most common cases this will be enough to get what you need.