Checking the String whether it is the Number(Double) of - swift

Question. It is necessary to make check the String whether it is the Number(Double)?
Exemple:
var s1:String = "df1231"
var s2:String = "1231,3123"
If s1.isDouble {
Println("True.This Number!")
} else {
Println("False.This not Number!") //Will give it
}
If s2.isDouble {
Println("True.This Number!") //Will give it
} else {
Println("False.This not Number!")
}

Not sure what your needs are exactly, but the most straightforward way to do it could be:
func isDouble(text:String) -> Bool {
guard let _ = Double(text.stringByReplacingOccurrencesOfString(",", withString: ".")) else { return false }
return true
}
isDouble("df1231") // returns false
isDouble("1231,3123") // returns true
You can copy paste it to Playground to see it work.

Related

How can I use UTType for comparing in a condition in Swift?

I am getting a folder url from user and then looking to find any mp3 files in that folder, the question itself in title and me just looking to use UTType in process.
As you can see I took all steps in codes just need last step in isMP3 function to finish the puzzle. So how can I use a path or URL and fining out the UTType of it and using it for comparing.
Also in my approach Xcode gave an error and says:
Cannot find 'UTType' in scope
Not sure why I have this error, normally it should Not be case, because it is type defined by Apple.
struct ContentView: View {
#State private var fileImporterIsPresented: Bool = false
var body: some View {
Button("Select your Folder") { fileImporterIsPresented = true }
.fileImporter(isPresented: $fileImporterIsPresented, allowedContentTypes: [.folder], allowsMultipleSelection: false, onCompletion: { result in
switch result {
case .success(let urls):
if let unwrappedURL: URL = urls.first {
if let contents = try? FileManager.default.contentsOfDirectory(atPath: unwrappedURL.path) {
contents.forEach { item in
if isMP3(path: unwrappedURL.path + "/" + item) {
print(item)
}
}
}
}
case .failure(let error):
print("Error selecting file \(error.localizedDescription)")
}
})
}
}
func isMP3(path: String) -> Bool {
// trying use UTType here
if URL(fileURLWithPath: path).??? == UTType.mp3 {
return true
}
else {
return false
}
}
To use UTType you have to import explicit package
import UniformTypeIdentifiers
it can be something like
func isMP3(path: String) -> Bool {
if let type = UTType(filenameExtension: URL(fileURLWithPath: path).pathExtension), type == UTType.mp3 {
return true
}
else {
return false
}
}
Here's another solution that uses URLResourceValues.contentType with a fallback to UTType(filenameExtension:):
import UniformTypeIdentifiers
func isMP3(path: String) -> Bool {
if let contentType = URL(fileURLWithPath: path).contentType,
contentType.conforms(to: .mp3)
{
return true
}
else {
return false
}
}
extension URL {
var contentType: UTType? {
if let resourceValues = try? resourceValues(forKeys: [.contentTypeKey]),
let contentType = resourceValues.contentType {
return contentType
} else if let contentType = UTType(filenameExtension: pathExtension) {
return contentType
} else {
return nil
}
}
}

How to get context of a sentence

So i'm working a an app that can patch words that are broken.
Lets take:
mny people say there is a error in this sentence
With swift here we can us UITextChecker and get a wonderful result of what the word mny could actually be... However, i actually get a couple of choices, one of which is many and among the other you have money so obviously money wouldn't fit in very well in this sentence. Are there any way to check if the sentence itself is logical?
Consider that this still needs to be improved. I updated this swift 3 solution to Swift 5. Worth to mention that it was originally inspired by this python tutorial
Create a new iOS project, add there a text file named bigtext.txt which will contain this text. This will be our "learning" dictionary.
Then in ViewController:
import UIKit
import NaturalLanguage
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let inputString = "mny people say there is a error in this sentence"
var newString = inputString
// Read a text file and "study" the model
guard let path = Bundle.main.path(forResource: "bigtext", ofType: "txt") else {
print("Path not available")
return
}
let checker = SpellChecker(contentsOfFile: path)
// better to use this to iterate between words in a sentence
let tokenizer = NLTokenizer(unit: .word)
tokenizer.string = inputString
tokenizer.enumerateTokens(in: inputString.startIndex..<inputString.endIndex) { tokenRange, _ in
let word = String(inputString[tokenRange])
let checked = checker?.correct(word: word)
let candidates = checker?.candidates(word: word)
if word == checked {
print("\(word) unchanged")
} else {
if let checked = checked {
newString.replaceSubrange(tokenRange, with: checked)
}
print("Correct:\t\(word) -> \(String(describing: checked))")
print("Candidates:\t\(word) -> \(String(describing: candidates))")
}
return true
}
print("Result: \(newString)")
}
}
func edits(word: String) -> Set<String> {
if word.isEmpty { return [] }
let splits = word.indices.map {
(word[word.startIndex..<$0], word[$0..<word.endIndex])
}
let deletes = splits.map { $0.0 + String($0.1.dropFirst()) }
let transposes: [String] = splits.map { left, right in
if let fst = right.first {
let drop1 = String(right.dropFirst())
if let snd = drop1.first {
let drop2 = String(drop1.dropFirst())
return "\(left)\(snd)\(fst)\(drop2)"
}
}
return ""
}.filter { !$0.isEmpty }
let alphabet = "abcdefghijklmnopqrstuvwxyz"
let replaces = splits.flatMap { left, right in
alphabet.map { "\(left)\($0)\(String(right.dropFirst()))" }
}
let inserts = splits.flatMap { left, right in
alphabet.map { "\(left)\($0)\(right)" }
}
let setString = [String(deletes.first!)] + transposes + replaces + inserts
return Set(setString)
}
struct SpellChecker {
var knownWords: [String:Int] = [:]
mutating func train(word: String) {
if let idx = knownWords[word] {
knownWords[word] = idx + 1
}
else {
knownWords[word] = 1
}
}
init?(contentsOfFile file: String) {
do {
let text = try String(contentsOfFile: file, encoding: .utf8).lowercased()
let words = text.unicodeScalars.split(whereSeparator: { !("a"..."z").contains($0) }).map { String($0) }
for word in words { self.train(word: word) }
}
catch {
return nil
}
}
func knownEdits2(word: String) -> Set<String>? {
var known_edits: Set<String> = []
for edit in edits(word: word) {
if let k = known(words: edits(word: edit)) {
known_edits.formUnion(k)
}
}
return known_edits.isEmpty ? nil : known_edits
}
func known<S: Sequence>(words: S) -> Set<String>? where S.Iterator.Element == String {
let s = Set(words.filter { self.knownWords.index(forKey: $0) != nil })
return s.isEmpty ? nil : s
}
func candidates(word: String) -> Set<String> {
guard let result = known(words: [word]) ?? known(words: edits(word: word)) ?? knownEdits2(word: word) else {
return Set<String>()
}
return result
}
func correct(word: String) -> String {
return candidates(word: word).reduce(word) {
(knownWords[$0] ?? 1) < (knownWords[$1] ?? 1) ? $1 : $0
}
}
}
Will output you:
Correct: mny -> Optional("may")
Candidates: mny -> Optional(Set(["any", "ny", "may", "many"]))
people unchanged
say unchanged
there unchanged
is unchanged
a unchanged
error unchanged
in unchanged
this unchanged
sentence unchanged
Result: may people say there is a error in this sentence
Please, consider that we took first correction candidate.
Need first to clarify ourselves the word order and understand the sentence context.

I want to check the validation for both mobile number and email id in single textfield. How should I validate this?

I want to check the validation for both "Email id " and "mobile number" in single textfield. How should I validate the conditions for the same textfield?
Maybe this will help:
extension String {
var isPhoneNumber: Bool {
do {
let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
let matches = detector.matches(in: self, options: [], range: NSMakeRange(0, self.count))
if let res = matches.first {
return res.resultType == .phoneNumber && res.range.location == 0 && res.range.length == self.count
} else {
return false
}
} catch {
return false
}
}
}
extension String {
var isInt: Bool {
return Int(self) != nil
}
}
func isValidEmail(testStr:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
return emailTest.evaluate(with: testStr)
}
if textField.text.characterCount > 6 {
if textField.text.isInt == true {
print("this might be users phone number"
} else if isValidEmail(testStr:textField.text) {
print("this might be users mail")
} else {
print("user entered wrong value or nothing")
}

Sorting mixed String-Int Strings numerically as the primary order, then alphabetically in swift

For a String which have both String and Int values (one of each) is it possible to do simple sort that will give the items ordered in numerical order as the primary order and alphabetical as the secondary order
var nameArray = ["Dave7", "Bob8", "Cathy9", "Henry10", "Susan10", "Pat11", "Steve12", "Dan12", "Ken1", "Sean2", "Howard3", "Dixie3", "Newman5", "Billy6"]
var sortedNameArray = nameArray.sort { $0.compare($1, options: .NumericSearch) == .OrderedAscending }
print(sortedNameArray) // gives the following:
Don't want this -> ["Billy6", "Bob8", "Cathy9", "Dan12", "Dave7", "Dixie3", "Henry10", "Howard3", "Ken1", "Newman5", "Pat11", "Sean2", "Steve12", "Susan10"]
Even though .NumericSearch was used the result is alphabetical.
I was able to get the desired result using a custom binary tree. Which gives the results:
Ken1 Sean2 Dixie3 Howard3 Newman5 Billy6 Dave7 Bob8 Cathy9 Henry10 Susan10 Pat11 Dan12 Steve12
But is there a simpler solution?
extension String {
var integerValue: Int? {
return Int(self)
}
}
func extractValueFromString(theString:String)->Int{
var catNumber: [Character] = []
//print("theString \(theString)")
for character in theString.characters{
var characterString = String(character)
if var value = characterString.integerValue { //if we don't check program crashes
//if numberSet.contains(Int(String(character))!) { //another way to check but redundant here
catNumber.append(character)
//print(catNumber)
// }
}
}
let numberString = String(catNumber)
return Int(numberString)!
}
class Node{
//nodes now only arrange strings
var data = ""
var value = Int()
var left:Node?;
var right:Node?;
deinit {
//print("deleting \(data)")
// print("node deleted")
}
init(data:String){
self.data = data;
//print(data)
}
}
class binaryTreeSort{
var root:Node?
init(){
}
deinit {
//print("tree deleted")
}
func getRoot()->Node{
return root!
}
func insertNewValue(data:String){
let newNode = Node(data:data)
var node:Node? = root
if (node == nil){
root = newNode
}
while (node != nil) {
let currentValue = node?.data
if currentValue == ""{
node?.data = data
return
}
if currentValue == data {
//we don't want duplicates.
return
}
if extractValueFromString(currentValue!) < extractValueFromString(data) {
if (node!.right != nil) {
node = node!.right
//print("Going Right at data \(node!.data)")
}else{
node!.right = newNode
//print("Going New Right at data \(node!.data)")
return
}
}else if extractValueFromString(currentValue!) == extractValueFromString(data){
if currentValue < data {
if (node!.right != nil) {
node = node!.right
//print("Going Right at data \(node!.data)")
}else{
node!.right = newNode
//print("Going New Right at data \(node!.data)")
return
}
}else{
if (node!.left != nil) {
//print("Going Left at data \(node!.data)")
node = node!.left
}else{
node!.left = newNode
//print("Going New Left at data \(node!.data)")
return
}
}
}
else{
if (node!.left != nil) {
//print("Going Left at data \(node!.data)")
node = node!.left
}else{
node!.left = newNode
//print("Going New Left at data \(node!.data)")
return
}
}
}
}
func inorderPrint(baseNode:Node){
if(baseNode.left != nil)
{
inorderPrint(baseNode.left!);
//print(" \(baseNode.data)")
}
print("\(baseNode.data)")
if(baseNode.right != nil)
{
inorderPrint(baseNode.right!)
//print(" \(baseNode.data)")
}
}
func reverseOrderPrint(baseNode:Node){
if(baseNode.right != nil)
{
reverseOrderPrint(baseNode.right!)
//print(" \(baseNode.data)")
}
print("\(baseNode.data)")
if(baseNode.left != nil)
{
reverseOrderPrint(baseNode.left!);
//print(" \(baseNode.data)")
}
}
}
var myBinaryTreeSort:binaryTreeSort? = binaryTreeSort()
for item in nameArray{
//print(item)
myBinaryTreeSort!.insertNewValue(item)
}
myBinaryTreeSort!.inorderPrint(myBinaryTreeSort!.getRoot())
print("---------------")
myBinaryTreeSort!.reverseOrderPrint(myBinaryTreeSort!.getRoot())
myBinaryTreeSort = nil //delete the tree
Use map to split the names into parts, sort to sort by number and name, and then map to restore the original:
func splitName(name:String) -> (String, Int) {
if let range = name.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()) {
return (name[name.startIndex..<range.startIndex], Int(name[range.startIndex..<name.endIndex])!)
} else {
return (name, 0)
}
}
print(nameArray.map(splitName).sort({ lhs, rhs in
if lhs.1 < rhs.1 {
return true
} else if lhs.1 > rhs.1 {
return false
} else {
return lhs.0 < rhs.0
}
}).map({ "\($0.0)\($0.1)" }))
Some other ways it could be done would be to maintain element 0 of the tuple as the full name (with numbers) and then the final map just becomes map({ $0.0 }) Depending on sizes, this may be more optimal than splitting the name each time it's compared.
If you have an array, you can sort with a custom closure.
For example:
nameArray.sort({extractValueFromString($0) < extractValueFromString($1)})
Will get you close. You just need to check if they are equal and return $0 < $1 instead.
Here's how I solved this, doing something similar to what #Lou-Franco alluded to:
func endInteger(word: String) -> Int {
if let range = word.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()){
let numberSubstring = word.substringFromIndex(range.startIndex)
return Int(numberSubstring) ?? 0
}
return 0
}
let sortedArray = yourArray.sort{endInteger($1) > endInteger($0)}

If let statement with multiple returns from function in swift

Say I have a function
func function1() -> (result:Bool, data:String){
return(false, "false")
}
and I want to use the return value of the Bool in an if let statement so,
if let value = function1 {
//code
} else {
//code
}
How would I get this to work? I can't seem to see it in the swift docs, as it just aludes to it being a returned tuple, which you can access with dot notation, but only if you set the return to be a tuple first - so for example this would work
var value = function1()
if value.result {
////code
} else {
//code
}
works, but I'd like to fit it all into the actual if else if possible. Any ideas?
I would suggest the use of a computed property.
func someFunc() {
if let value = computedProperty where value.result {
print(value.data)
} else {
// Do something else
}
}
var computedProperty: (result: Bool, data: String)? {
return (true, "FooBar")
}
or using a function
func someFunc() {
if let value = anotherFunc() where value.result {
print(value.data)
} else {
// Do something else
}
}
func anotherFunc() -> (result: Bool, data: String)? {
return (true, "FooBar")
}
Hope this helps :)
Swift 2.1 Properties
You could pattern match with a switch statement.
switch function1() {
case (true, let string):
print(string)
default:
// else stuff here
}
With this type on if you need optional return type from your function like this:
func function1() -> (result:Bool, data:String)? {
return(false, "false")
}
if let value = function1() {
//code
} else {
//code
}