I want to delete last integers value swift - swift

I want to delete only integer value from any string. Is it possible or not?
let string = "kjgd5676idbh123456"
i want to result this string = kjgd5676idbh
I want to delete only the last integer value. How to remove the last integer value?

If you would like to delete the whole value 123456 you can use regex \\d+ to match any number with 1 digit or more and anchor it to the end of the string using the dolar sign $
let str = "kjgd5676idbh123456"
if let index = str.range(of: "\\d+$", options: .regularExpression)?.lowerBound {
print("Last Number:", str[index...]) // 123456
print("Prefix:", str[..<index]) // kjgd5676idbh
}
If you need to remove a single digit suffix you just need to remove the plus sign of your regex. "\\d$"

Search backwards for the first non-digit character and drop the trailing digits
let string = "kjgd5676idbh123456"
let result : String
if let range = string.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted, options: .backwards) {
result = String(string[..<range.upperBound])
} else {
result = Int(string) == nil ? string : ""
}

Related

Swift get decimal value for String characters

Is it possible to get the decimal value for String characters in Swift?
something like:
let words:String = "1 ring to rule them all"
var value:Int = 0
for i in 0..<words.count {
let char = words[words.index(words.startIndex,offsetBy:i)]
value += Int(char.decimal)
}
where the first character in "1 ring to rule them all" is 49. Possible?
you could try this:
let words = "1 ring to rule them all"
var value: Int = 0
for i in 0..<words.count {
let char = words[words.index(words.startIndex,offsetBy:i)]
if let val = char.asciiValue {
print("----> char: \(char) val: \(val)") // char and its "decimal" value
value += Int(val)
}
}
print("\n----> value: \(value) \n") // meaningless total value
ok, looks like this is the way:
let characterString = "蜇"
let scalars = characterString.unicodeScalars
let ui32:UInt32 = scalars[scalars.startIndex].value
If you want to add up the Unicode values associated with a string, it would be:
var value = 0
for character in string {
for scalar in character.unicodeScalars {
value += Int(scalar.value)
}
}
Or, alternatively:
let value = string
.flatMap { $0.unicodeScalars }
.compactMap { $0.value }
.reduce(0, +)
While the above adds the values, as requested, if you are trying to get a numeric representation for a string, you might consider using hashValue, or checksum, or CRC, or the like. Simply summing the values will not be able to detect, for example, character transpositions. It just depends upon your use-case for this numeric representation of your string.

Swift Strings and [Character]

I have this code:
let txt = "over 100MB+ of text..."
let tokenizedText = Array (txt)
let regex = try NSRegularExpression (pattern: "(?s)<tu>.*?</tu>")
let r = regex.matches (in: txt, range: NSRange (txt.startIndex..<txt.endIndex, in: txt))
for match in r {
let befOfMatch = match.range.lowerBound
let endOfMatch = match.range.lowerBound + match.range.length
// check the result
if tokenizedText[begOfMatch] != "<" {
print ("error") // from time to time!!!!
}
}
=> regex.matches produces integer ranges that are not always in sync with the characters array.
I know that UTF8 does not have a one-to-one correspondance between bytes and characters, but how to sync Strings and [Characters] ? I would need to:
-- retrieve the sequence of characters inside the matching sequences as [Character]
-- insert a tag (e.g. <found> ... </found>) around each matching sequence in the buffer (string)
How can I do that?
The issue there is that NSRange it is based on UTF16 therefore the location of the resulting NSRange it is not necessarily the same as the character position in the array of characters (Not every character can be represented by a single byte). You need to convert the resulting NSRange to Range and check the original string using the lowerbound of the String Range:
let txt = "over 100MB+ of text... <tu>whatever</tu>"
let tokenizedText = Array (txt)
let regex = try NSRegularExpression (pattern: "(?s)<tu>.*?</tu>")
let r = regex.matches (in: txt, range: NSRange (txt.startIndex..<txt.endIndex, in: txt))
for match in r {
if let range = Range(match.range, in: txt) {
print (txt[range])
if txt[range.lowerBound] == "<" {
print(true)
} else {
print(false)
}
}
}

Format String left of multiple characters in Swift 5?

I have some Strings that vary in length but always end in "listing(number)"
myString = 9AMnep8MAziUCK7VwKF51mXZ2listing28
.
I want to get the String without "listing(number)":
9AMnep8MAziUCK7VwKF51mXZ2
.
Methods I've tried such as .index(of: ) only let you format based off one character. Any simple solutions?
A possible solution is to search for the substring with Regular Expression and remove the result (replace it with empty string)
let myString = "9AMnep8MAziUCK7VwKF51mXZ2listing28"
let trimmedString = myString.replacingOccurrences(of: "listing\\d+$", with: "", options: .regularExpression)
\\d+ searches for one ore more digits
$ represents the end of the string
Alternatively without creating a new string
var myString = "9AMnep8MAziUCK7VwKF51mXZ2listing28"
if let range = myString.range(of: "listing\\d+$", options: .regularExpression) {
myString.removeSubrange(range)
}
Another option is to split the string in parts with "listing" as separator
let result = myString.components(separatedBy: "listing").first
So to solve your issue find the code below with few comments written to try and explain each steps have taken. kindly note i have modified or arrived at this solution using this links as a guide.
https://stackoverflow.com/a/40070835/6596443
https://www.dotnetperls.com/substring-swift
extension String {
//
// Paramter inputString: This is the string you want to manipulate
// Paramter- startStringOfUnwanted: This is the string you want to start the removal or replacement from
//return : The expected output you want but can be emptystring if unable to
static func trimUnWantedEndingString(inputString: String,startStringOfUnwanted: String) -> String{
//Output string
var outputString: String?
//Getting the range based on the string content
if let range = myString.range(of: startStringOfUnwanted) {
//Get the lowerbound of the range
let lower = range.lowerBound
//Get the upperbound of the range
let upper = range.upperBound
//Get the integer position of the start index of the unwanted string i added plus one to ensure it starts from the right position
let startPos = Int(myString.distance(from: myString.startIndex, to: lower))+1
//Get the integer position of the end index of the unwanted string i added plus one to ensure it starts from the right position
let endPos = Int(myString.distance(from: myString.startIndex, to: upper))+1
//Substract the start int from the end int to get the integer value that will be used to get the last string i want to stop trimming at
let endOffsetBy = endPos-startPos
//get thes string char ranges of values
let result = myString.index(myString.startIndex, offsetBy: 0)..<myString.index(myString.endIndex, offsetBy: -endOffsetBy)
//converts the results to string or get the string representation of the result and then assign it to the OutputString
outputString = String(myString[result]);
}
return outputString ?? "";
}
}
let myString = "9AMnep8MAziUCK7VwKF51mXZ2listing28"
String.trimUnWantedEndingString(inputString: myString, startStringOfUnwanted:"listing")

Remove leading characters and zero in swift

I tried to remove some characters from string in Swift 4, says: I have
QC00012345, return 12345
QC00009876, return 9876
QC12345678, return 12345678
removing first two characters and those leading zeros.
I looked around in here, people are just using dropFirst then convert
String into Int then convert it back to String.
Is there any better way?
You could use a regular expression and dropFirst:
let str = "QC00009876"
let clean = str.dropFirst(2).replacingOccurrences(of: "^0*", with: "", options: .regularExpression)
The expression ^0* means "zero or more 0 characters at the start of the string".
Or with just a regular expression:
let str = "QC00009876"
let clean = str.replacingOccurrences(of: "^..0*", with: "", options: .regularExpression)
The expression ^..0* means "any two characters followed by zero or more 0 characters at the start of the string".
You can simply use drop(while:):
let test = "QC00012345"
let num = test.dropFirst(2).drop { $0 == "0"}
You can also create a ClosedRange<String> and use it as predicate if you don't want to drop first two characters manually:
let num = test.drop { !("1"..."9" ~= $0) }
print(num) // 12345
or check if a string from 1 to 9 does not contain the character:
let num = test.drop { !"123456789".contains($0) }
edit/update:
Swift 5 or later
Using the Character property isWholeNumber
let num = test.drop { !$0.isWholeNumber || $0 == "0" }

Return results from regular expression pattern matching

I have a string (HTML in this example case) which contains the same pattern for displaying the results of sports games. So, the HTML tags are known, but the values for each game are not.
In Perl, we can do this:
if ( $content =~ /\<\/a\>\<br\>(\d+)\<\/span\>\<br\>(\d+)\-(\d+).+\<\/a\>\<br\>(\d+)\<\/span\>\<br\>(\d+)\-(\d+)/) {
$visitingTeamScore = $1; // $1 is the 1st matched digit
$visitingTeamWins = $2; // $2 is the 2nd matched digit
$visitingTeamLosses = $3; // Etc
$homeTeamScore = $4;
$homeTeamWins = $5;
$homeTeamLosses = $6;
}
which returns the digits inside the parentheses, in this case 6 total integers of varying digit lengths. We can then assign those matches to variables.
From an answer in this question: Swift Get string between 2 strings in a string, I have the following Swift code:
extension String {
func sliceFrom(start: String, to: String) -> String? {
return (rangeOfString(start)?.endIndex).flatMap { sInd in
(rangeOfString(to, range: sInd..<endIndex)?.startIndex).map { eInd in
substringWithRange(sInd..<eInd)
}
}
}
}
let firstMatch = content?.sliceFrom("</a><br>", to: "</span>") // The first integer in the string
The problem comes in when getting the 4th integer which is also between </a\><br> and </span> so the resulting match will be the first digit again.
I can manually count the characters (which itself isn't a perfect science because the digits in each integer can differ) to do something ugly like:
let newRawHTML = content![content!.startIndex.advancedBy(15)...content!.startIndex.advancedBy(5)]
Another possibility is to remove anything matched already from the string, making it shorter for each subsequent search (which I'm not sure how to implement.) What's the way to do this? Is there any way in Swift to "pluck out" the matches?
The code you have shown as a Perl example, uses regular expression.
And in case the pattern is getting a little bit complex, you'd better use NSRegularExpression directly.
let pattern = "</a><br>(\\d+)</span><br>(\\d+)-(\\d+).+</a><br>(\\d+)</span><br>(\\d+)-(\\d+)"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
if let match = regex.firstMatchInString(content, options: [], range: NSRange(0..<content.utf16.count)) {
let visitingTeamScore = (content as NSString).substringWithRange(match.rangeAtIndex(1))
let visitingTeamWins = (content as NSString).substringWithRange(match.rangeAtIndex(2))
let visitingTeamLosses = (content as NSString).substringWithRange(match.rangeAtIndex(3))
let homeTeamScore = (content as NSString).substringWithRange(match.rangeAtIndex(4))
let homeTeamWins = (content as NSString).substringWithRange(match.rangeAtIndex(5))
let homeTeamLosses = (content as NSString).substringWithRange(match.rangeAtIndex(6))
//...use the values
}