How to remove 1 component in a string? Swift - ios

I have this string "01:07:30" and I would like to remove the zero in "01" and keep everything else the same. My final string should look like this
"1:07:30"
Is there a way to do so in Swift? Thank you so much!

Try the following. This will create a string, check to see if the first character is 0 if it is remove it. Otherwise do nothing.
var myString = "01:07:30"
if myString.first == "0" {
myString.remove(at: myString.startIndex)
}
print(myString) // 1:07:30
The final result is the string will now be 1:07:30 instead of 01:07:30.

If I'm best understanding your question, you want to replace the occurrences of "01" with "1" in your string, so you can use regex or the string functionality it self
simply:
let searchText = "01"
let replaceWithValue = "1"
let string = "01:07:08:00:01:01"
let newString = string.replacingOccurrences(of: searchText, with: replaceWithValue) // "1:07:08:00:1:1"
If you want to replace the fist occurrence only, simply follow this answer:
https://stackoverflow.com/a/33822186/3911553

If you just want to deal with string here is one of many solution:
var myString = "01:07:30"
let list = myString.components(separatedBy: ":")
var finalString = ""
for var obj in list{
if obj.first == "0" {
obj.removeFirst()
}
finalString += finalString.count == 0 ? "\(obj)" : ":\(obj)"
}
print(finalString)

Related

How to trim several textfield in swift at once?

I have several textfield in a page. Currently i'm trimming every textfield one by one like code below.
public struct CustomerAddressDetail: Encodable {
public var fullname: String?
public var identifierNumber: String?
}
var customerInfoDetail = CustomerInfoDetail()
customerInfoDetail.fullname = itemsInput[0][0].value?.trimmingCharacters(in: .whitespaces) ?? ""
customerInfoDetail.identifierNumber = itemsInput[0][1].value?.trimmingCharacters(in: .whitespaces) ?? ""
I try to trim multiple value at once. Because it looks like a bad way to trim it one by one
Is it really like that ? Or is there any better way to trim multiple item ?
It looks bad to you because you have duplicate code. A nicer way to it is using iteration or map like this:
let stringlist: [String] = ["a ", "b ", "c "]
let trimmedlist = stringlist.map { s in
return s.trimmingCharacters(in: .whitespaces)
}

How to regex string that includes html

I have this string which is part of a larger string with multiple occurrences of "content" and "/content": I want to capture the whole string between "content ..." and "/content".
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">RATING: ★★★★<br/>
TAGS: Fiction, General, Science Fiction<br/>
SERIES: 20 SienceFiction Greats [19]<br/>
<p class="description">SUMMARY:<br/>Luna is an open colony and the regime is a harsh one....</p></div>
</content>
I want to capture all between "content type="xhtml"" and "/content"
I tried this code:
let regexPattern = "<content type=\"xhtml\">.*</content>"
let result:[String] = matches(for: regexPattern, in: dataString)
but it returns an empty array.
Your regex pattern is close. You do not have any capturing groups within the regex. A capturing group is defined as any pattern between (). So with a little adjustment of the regex you will get a match. The updated Regex should look like this:
let regexPattern = "<content type=\"xhtml\">(.*)<\/content>"
Well I found a solution as the .* pattern captures everything from the first occurrence of "content" to the last occurrence of "/content".
so this is my solution: get an array of "content" occurrences and an array of "/content" occurrences, from these arrays I can calculate the ranges I need from the string
private func getXHTMLContentFromDataString(dataString: String) -> [String] {
var contentStringArray: [String] = []
let startString: String = "<content type=\"xhtml\">"
let endString: String = "</content>"
var isFound = true
var currentString = dataString
while isFound == true && currentString.characters.count > 0 {
if let contentStartRange = currentString.range(of: startString), let contentEndRange = currentString.range(of: endString) {
isFound = true
let contentStr: String = currentString[contentStartRange.upperBound .. < contentEndRange.lowerBound]
contentStringArray.append(contentStr)
currentString = currentString[contentEndRange.upperBound .. <currentString.endIndex]
} else {
isFound = false
}
}
return contentStringArray
}

How to take NSRange in swift?

I am very much new to swift language. I am performing some business logic which needs to take NSRange from given String.
Here is my requirement,
Given Amount = "144.44"
Need NSRange of only cent part i.e. after "."
Is there any API available for doing this?
You can do a regex-based search to find the range:
let str : NSString = "123.45"
let rng : NSRange = str.range("(?<=[.])\\d*$", options: .RegularExpressionSearch)
Regular expression "(?<=[.])\\d*$" means "zero or more digits following a dot character '.' via look-behind, all the way to the end of the string $."
If you want a substring from a given string you can use componentsSeparatedByString
Example :
var number: String = "144.44";
var numberresult= number.componentsSeparatedByString(".")
then you can get components as :
var num1: String = numberresult [0]
var num2: String = numberresult [1]
hope it help !!
Use rangeOfString and substringFromIndex:
let string = "123.45"
if let index = string.rangeOfString(".") {
let cents = string.substringFromIndex(index.endIndex)
print("\(cents)")
}
Another version that uses Swift Ranges, rather than NSRange
Define the function that returns an optional Range:
func centsRangeFromString(str: String) -> Range<String.Index>? {
let characters = str.characters
guard let dotIndex = characters.indexOf(".") else { return nil }
return Range(dotIndex.successor() ..< characters.endIndex)
}
Which you can test with:
let r = centsRangeFromString(str)
// I don't recommend force unwrapping here, but this is just an example.
let cents = str.substringWithRange(r!)

Replace part of string with lower case letters - Swift

I have a Swift based iOS app and one of the features allows you to comment on a post. Anyway, users can add "#mentions" in their posts to tag other people. However I want to stop the user from adding a username with a capital letter.
Is there anyway I can convert a string, so that the #usernames are all in lowercase?
For example:
I really enjoy sightseeing with #uSerABC (not allowed)
I really enjoy sightseeing with #userabc (allowed)
I know there is a property for the string in swift called .lowercaseString - but the problem with that, is that it makes the entire string lowercase and thats not what I want. I only want the #username to be in lower case.
Is there any way around this with having to use the .lowercase property.
Thanks for your time, Dan.
This comes from a code I use to detect hashtags, I've modified to detect mentions:
func detectMentionsInText(text: String) -> [NSRange]? {
let mentionsDetector = try? NSRegularExpression(pattern: "#(\\w+)", options: NSRegularExpressionOptions.CaseInsensitive)
let results = mentionsDetector?.matchesInString(text, options: NSMatchingOptions.WithoutAnchoringBounds, range: NSMakeRange(0, text.utf16.count)).map { $0 }
return results?.map{$0.rangeAtIndex(0)}
}
It detects all the mentions in a string by using a regex and returns an NSRange array, by using a range you have the beginning and the end of the "mention" and you can easily replace them with a lower case version.
Split the string into two using the following command -
let arr = myString.componentsSeparatedByString("#")
//Convert arr[1] to lower case
//Append to arr[0]
//Enjoy
Thanks to everyone for their help. In the end I couldn't get any of the solutions to work and after a lot of testing, I came up with this solution:
func correctStringWithUsernames(inputString: String, completion: (correctString: String) -> Void) {
// Create the final string and get all
// the seperate strings from the data.
var finalString: String!
var commentSegments: NSArray!
commentSegments = inputString.componentsSeparatedByString(" ")
if (commentSegments.count > 0) {
for (var loop = 0; loop < commentSegments.count; loop++) {
// Check the username to ensure that there
// are no capital letters in the string.
let currentString = commentSegments[loop] as! String
let capitalLetterRegEx = ".*[A-Z]+.*"
let textData = NSPredicate(format:"SELF MATCHES %#", capitalLetterRegEx)
let capitalResult = textData.evaluateWithObject(currentString)
// Check if the current loop string
// is a #user mention string or not.
if (currentString.containsString("#")) {
// If we are in the first loop then set the
// string otherwise concatenate the string.
if (loop == 0) {
if (capitalResult == true) {
// The username contains capital letters
// so change it to a lower case version.
finalString = currentString.lowercaseString
}
else {
// The username does not contain capital letters.
finalString = currentString
}
}
else {
if (capitalResult == true) {
// The username contains capital letters
// so change it to a lower case version.
finalString = "\(finalString) \(currentString.lowercaseString)"
}
else {
// The username does not contain capital letters.
finalString = "\(finalString) \(currentString)"
}
}
}
else {
// The current string is NOT a #user mention
// so simply set or concatenate the finalString.
if (loop == 0) {
finalString = currentString
}
else {
finalString = "\(finalString) \(currentString)"
}
}
}
}
else {
// No issues pass back the string.
finalString = inputString
}
// Pass back the correct username string.
completion(correctString: finalString)
}
Its certainly not the most elegant or efficient solution around but it does work. If there are any ways of improving it, please leave a comment.

String componentsSeparatedByString do one time

I have a string:
let mystring = "key=value=value=value=value"
When i did:
let ar = mystring.componentsSeparatedByString("=")
i get:
["key", "value", "value", "value", "value"]
but i need do split only once, like componentsSeparatedByString("=", 1), to get:
["key", "value=value=value=value"]
With Swift 2.1, you can use the split function as follows to do what you want:
let result = string.characters.split("=", maxSplit: 1, allowEmptySlices: true)
Some example code to test this would be:
let string = "key=value=value=value=value"
let result = string.characters.split("=", maxSplit: 1, allowEmptySlices: true)
print(String(result[0])) // "key"
print(String(result[1])) // "value=value=value=value"
This should do the job
func extract(rawData: String) -> [String]? {
let elms = rawData.characters.split("=", maxSplit: 1).map { String($0) }
guard let
key = elms.first,
value = elms.last
where elms.count == 2 else { return nil }
return [key, value]
}
Example:
let rawData = "key=value=value=value=value"
extract(rawData) // > ["key", "value=value=value=value"]
Please note the extract function does an optional array of strings. Infact if the input string does not contain at least an = then nil is returned.
The code has been tested with the Swift 2.1 and Xcode Playground 7.1.1.
Hope this helps.
You're probably going to have to write your own custom code to do that, using either NSScanner or rangeofString:options:range:
EDIT:
Actually, it sounds like the Swift String class's split function, with its maxSplit parameter, will do what you need. Take a look at the link in Preston's answer.
let mystring = "key=value=value=value=value"
let result = split(mystring as String, { $0 == "=" }, maxSplit: 1, allowEmptySlices: true)
result should now be [key, value=value=value=value]
Thanks for answers, i found working solution for swift2:
let mystring = "key=value=value=value=value"
mystring.characters.split(1, allowEmptySlices: true, isSeparator: { $0 == "=" }).map(String.init)
Try this: (tested and working in playground)
var key = str.substringToIndex(str.rangeOfString("=")!.startIndex)
var value = str.substringFromIndex(str.rangeOfString("=")!.startIndex.advancedBy(1))
var resultingArray = [key, value]

Resources