I'm trying to delete numbers at the end of the string but I couldn't do that. How can I do it?
Example:
swift 23
ios 36
iphone 25
swift
ios
iphone
but also i want to show numbers at the begin.
example:
25 january 2018 my question
11 september 2001
UPDATE
That's my code:
func parseHTML(html: String) -> Void {
if let doc = try? HTML(html: html, encoding: .utf8) {
var showString = String()
for show in doc.css("ul[class^='topic'] li a"){
showString = show.text!.trimmingCharacters(in: CharacterSet.decimalDigits) //it's remove whole numbers
goster.append(showString)
}
UPDATE
The question changed so this answer probably won't work for you now.
A quick approach if there is always going to be a space or more in between is:
var str = "swift 23"
let newString = str.split(separator: " ").first
You can use String.replacingOccurences(of:,with:,options:) with a regex to only match digits at the end of your Strings.
let stringsWithNumbers = ["swift 23", "ios 36", "iphone 25","25 january 2018 my question","11 september 2001"]
let newStrings = stringsWithNumbers.map({$0.replacingOccurrences(of: "\\d+$", with: "", options: .regularExpression)})
print(newStrings)
Output:
["swift ", "ios ", "iphone ", "25 january 2018 my question", "11
september "]
If you also want to remove the whitespaces at the end of the Strings, just change the regex to "\\s*\\d+$".
Related
This question already has answers here:
trimmingCharacters not work on iOS 10.3 Xcode8.3
(6 answers)
Closed 3 years ago.
I am removing white space from a string with "trimmingCharacters" but space is not removing .
let number = "123 456"
let replaced = number.trimmingCharacters(in: .whitespaces)
print(username)
print(replaced)
Use replacingOccurrences(of:with:) method on String, i.e.
let number = "123 456"
let replaced = number.replacingOccurrences(of: " ", with: "")
print(replaced) //Output: 123456
Use String replacingOccurrences
let number = "123 456"
let replaced = number.replacingOccurrences(of: " ", with: "")
print(replaced)
or
Use Filter
let removed = number.filter{!$0.isWhitespace}
print(removed)
Output 123456
I am looking for a way to detect years e.g. 2019. The requirements I think would be that the numbers are in a row, have four digits and are not adjacent to letters or special characters. So I'd like to get the method to return "2019" in each of the following cases:
"2019"
"in 2019
"Before 2019, all IOS apps were written in one of 2 ways"
But exclude it from:
"1234z20191234
There are a lot of ways to detect the numbers in a string as seen here such as
let newString = origString
.components(separatedBy:CharacterSet.decimalDigits.inverted)
.joined(separator: "")
But they don't pull out each series of numbers to test for length and adjacency.
Data detector can try to pull out a date but going from the possible date to the year that might have been in the starting text seems error prone e.g. working with something like:
“2018-08-31 04:00:00 +0000”, “America/Los_Angeles”, 18000.0
Can anyone suggest a reliable way to retrieve a numerical year from a string?
You might use regular expression, searching for four digits ([0-9]{4}) between word boundaries (\b), e.g.
let strings = [
"2019",
"in 2019",
"Before 2019, all IOS apps were written in one of 2 ways",
"1234z20191234"
]
for string in strings {
if let range = string.range(of: #"\b[0-9]{4}\b"#, options: .regularExpression) {
let year = String(string[range])
print(year)
} else {
print("No year found")
}
}
Producing:
2019
2019
2019
No year found
Note, the above uses Swift 5’s Extended String Delimiters, #" and "#. If doing this in earlier Swift versions, you’ll want to just escape the backslashes with yet another backslash:
if let range = string.range(of: "\\b[0-9]{4}\\b", options: .regularExpression) {
...
}
Clearly if you want to narrow the range of four digit numbers recognized as years, you’d have to tweak the regular expression or supplement it with some logic. But your question doesn’t identify what criteria you want to use to detect years.
You can do this with a regular expression. This code will find all years in a given string. You can set the check to confirm the number is within whatever range you wish to accept.
func findYears(in text: String) -> [String] {
let yearRE = try! NSRegularExpression(pattern: "(?:\\b)[0-9]{4}(?:\\b)")
var results = [String]()
yearRE.enumerateMatches(in: text, range: NSRange(text.startIndex..<text.endIndex, in: text)) { (result, flags, stop) in
if let result = result {
let match = String(text[Range(result.range(at: 0), in: text)!])
// Set whatever range you wish to accept
if let year = Int(match), year > 1600 && year < 2200 {
results.append(match)
}
}
}
return results
}
let yearStrings = [
"2019",
"in 2019 and 2020",
"Before 2019, all IOS apps were written in one of 2 ways",
"1234z20191234",
"2018-08-31 04:00:00 +0000",
]
for yearString in yearStrings {
print(findYears(in: yearString))
}
Output:
["2019"]
["2019", "2020"]
["2019"]
[]
["2018"]
let's say I have a string
var a = "#bb #cccc #ddddd\u{ef}"
and i am setting it to textview like this
let text = a.trimmingCharacters(in: .whitespacesAndNewlines)
let textRemoved = text?.replacingOccurrences(of: "\u{ef}", with: "", options: NSString.CompareOptions.literal, range:nil)
textView.text = textRemove
I am trying to remove the \u{ef} character here. But in textRemoved it is not happening. Please help me how to do it.
I am using Xcode 10. Looks like below Xcode version than 10 is working
fine. is it a bug of Xcode 10?
This is a late answer but I struggled to replace "\u{ef}" in string as well. During debugging when hovered over string it showed presence of \u{ef} but when print in description it only showed space.
let str = "\u{ef} Some Title"
print(str) //" Some Title"
I tried replacingOccurrences(of: "\u{ef}", with: "", options: NSString.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces) but it failed as well.
So I used below snippet and it worked like wonder.
let modifiedStr = str.replacingOccurrences(of: "\u{fffc}", with: "", options: NSString.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces)
print(modifiedStr) //"Some Title"
Hope this helps someone!!
i also faced same issue for "\u{e2}". i have searched a lot but unable to find any answer. then i have tried below code , which works for me.
var newString = ""
for char in strMainString.unicodeScalars{
if char.isASCII{
newString += String(char)
}
}
Hope that will also work for you too.
In Xcode 10 Playground, string replaces for \u{00EF} is working.
var a = "#bb #cccc #ddddd\u{ef}"
a = a.replacingOccurrences(of: "\u{00EF}", with: "")
I hope that will work for you.
I tried the following and it worked like a charm:
replacingOccurrences(of: "�", with: " ", options: NSString.CompareOptions.literal, range: nil)
e.g. 1
let text = "\u{ef}\u{ef}\u{ef}\u{ef}😇哦哦哦"
let text1 = text.replacingOccurrences(of: "\u{fffc}", with: "", options: String.CompareOptions.literal, range: nil)
let text2 = text.replacingOccurrences(of: "\u{ef}", with: "", options: String.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces)
runnable
<img src="https://i.stack.imgur.com/styVo.png"/>
e.g. 2
let strBefore = textDocumentProxy.documentContextBeforeInput
let strAfter = textDocumentProxy.documentContextAfterInput
var textInput = strBefore + strAfter
let textInput2 = textInput.replacingOccurrences(of: "\u{ef}", with: "", options: String.CompareOptions.literal, range: nil)
let textInput1 = textInput.replacingOccurrences(of: "\u{fffc}", with: "", options: String.CompareOptions.literal, range: nil).trimmingCharacters(in: .whitespaces)
runnable
<img src="https://i.stack.imgur.com/xGHtW.png"/>
Similar to question but with \u{e2} symbol (fix is the same):
\u{e2} is not a character rather subset of UTF8 plane which starts with 0xE2 byte.
So look here, E2 are general punctuation symbols.
There many symbols actually which started with \u{e2} but not limited to it and full char can be represented f.e. with e2 80 a8 bytes (line separator).
That explains why shown in Xcode \u{e2} can't be replaced with replacingOccurrences... function. In order to filter out correct symbol you have to know what exact symbol it is, f.e. by using the snippet below:
"\u{2028}&😲".forEach { (char) in
print(Data(char.utf8).map { String(format: "%02x", $0) }.joined(separator: " "))
}
it prints to console:
e2 80 a8
26
f0 9f 98 b2
which are byte representation for each symbol.
Next step is to filter your string, go here and search in 3d column your bytes and unicode code point value is what you need (first column) and write it in swift code like "\u{2028}\u{206A}..." (depending on your sorting).
The final function may look like:
func removingE2Symbols() -> String {
let specialChars = "\u{202A}\u{202C}"
return filter { !specialChars.contains($0) }
}
Try this
extension String {
var asciiString: String {
return String(self.unicodeScalars.filter{ $0.isASCII })
}
}
It,s working Please check again:
let a = "#bb #cccc #ddddd\u{ef}"
let text = a.trimmingCharacters(in: .whitespacesAndNewlines)
let textRemoved = text.replacingOccurrences(of: "\u{ef}", with: "", options: NSString.CompareOptions.literal, range:nil)
print(textRemoved)
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}])
I'm storing heights in my database as 62 or 511 instead of 6 ft 2 or 5 ft 11.
This is how I prepare the string that will be saved:
let height = 6 ft 2
let myNewString = height.stringByReplacingOccurrencesOfString(" ft ", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
println(myNewString) // 62
What I'd like to do is now do the opposite thing when displaying back the data from the database.
So I'd like to take the returned "62" from the database and insert this string " ft " into it. My aim is to end up with "6 ft 2" to display on the app.
How can I do this?
I want to avoid storing two columns dedicated to height in my database. I only know how to concatenate strings but this isn't exactly concatenating a string. I am inserting it into an existing string.
I'd appreciate an efficient way to do this. Been looking around for a while now and can't seem to find my solution.
Thanks for your time.
Update:
After reading comments I'm wondering if it would be better to add a decimal point after the first char in string e.g. 4.2, 4.10, 5.4, 5.11, 6.2 etc
let height = 6 ft 2
let myNewString = height.stringByReplacingOccurrencesOfString(" ft ", withString: ".", options: NSStringCompareOptions.LiteralSearch, range: nil)
println(myNewString) // 6.2
It would probably be a better idea to store the height purely in inches (e.g. store 74 for 6'2").
Anyway:
let input = "62"
let feet = (input as NSString).substringToIndex(1)
let inches = (input as NSString).substringFromIndex(1)
let output = "\(feet) ft \(inches)"
If you don't like the use of NSString, you can avoid it this way:
let input = "62";
let feet = input.substringToIndex(input.startIndex.successor())
let inches = input.substringFromIndex(input.startIndex.successor())
let output = "\(feet) ft \(inches)"
Swift’s String conforms to RangeReplaceableCollectionType, which has a splice method – splice allows you to insert a collection into another collection. Since strings are collections, that means you can write:
var height = "62"
if !height.isEmpty {
height.splice(" ft ", atIndex: height.startIndex.successor())
} // height is now "6 ft 2"
Alternatively if you know you only want the first character before the “ft” you can do:
let height = "62"
if let feet = first(height) {
let inches = dropFirst(height)
let heightWithFt = "\(feet) ft \(inches)"
}