Swift: How to split a string and then extract specific substring? [duplicate] - ios

This question already has answers here:
Swift Regex for extracting words between parenthesis
(2 answers)
Closed 4 years ago.
Example String -
exampleString ( 123 )
I want two parts from the above string -
1-) exampleString by splitting
2-) 123 by splitting and then removing brackets and two spaces, one at each end
More specifically, I want to know how can I extract a string between
two brackets ( )
How to achieve that in swift 4.2?
Thanks

There is a solution below, it will extract any string between brackets into an array without brackets, it also gives you string without element as word as an array element:
var myString = "exampleString ( 123 ) "
//creates result array from String by separating elements by space
var result = myString.split(separator: " ")
//filters array to remove '(' and ')'
result = result.filter { $0 != "(" && $0 != ")" }
print(result)
Then if you want to build a String back from result array with string elements, do the following:
var resultString = result.joined(separator: " ")
print(resultString)
Might not be ideal, but it might be useful for you.

I found this beautiful String Extension for slicing a string. It is answered here -
Slice String Extension
extension String {
func slice(from: String, to: String) -> String? {
return (range(of: from)?.upperBound).flatMap { substringFrom in
(range(of: to, range: substringFrom..<endIndex)?.lowerBound).map { substringTo in
String(self[substringFrom..<substringTo])
}
}
}
}
Here I can simply get a substring like
let str = "exampleString ( 123 )"
print(str.slice(from: "( ", to: " )"))

Related

Swift Algorithm : how to get String that includes all substrings without repetition

Suppose you get an input like below:
hello
helloSwift
Swi
Apple
le
(total 5)
I want a function to receive the above inputs and return a String "helloSwiftApple".
The returning String must "include" all input Strings without repetitions. For instance, the returning String can't be "hellohelloSwiftSwiApplele" How can I do this with Swift?
Thanks in advance and sorry for my bad explanation. Just got started studying algorithm using Swift.
This is a bit of a "brute force" approach, but it may work for you.
split the string into an array a of unique "words"
loop through the array for i in 0..<a.count
remove element i word
does any element in a contain word?
if NO
add word to new array
put word back in a
return newArray joined into string
So, we can use this extension to remove duplicates from an array (Hacking with Swift):
extension Array where Element: Hashable {
func removingDuplicates() -> [Element] {
var addedDict = [Element: Bool]()
return filter {
addedDict.updateValue(true, forKey: $0) == nil
}
}
mutating func removeDuplicates() {
self = self.removingDuplicates()
}
}
and we can write a func like this:
func parseString(_ str: String) -> String {
// split the string into an array of "words" (no spaces)
var a1: [String] = str.components(separatedBy: " ").removingDuplicates()
// an array to hold the unique words
var a2: [String] = []
// for each word
for i in 0..<a1.count {
// remove the word from the array
let word = a1.remove(at: i)
// filter the remaining array by elements containing word
let n = a1.filter { $0.contains(word) }
// if no elements contain word
if n.count == 0 {
// append it to array of unique words
a2.append(word)
}
// put the word back into the full array
a1.insert(word, at: i)
}
// change "-" to "" for no separators
return a2.joined(separator: "-")
}
A quick test like this:
let test: [String] = [
"1 hello helloSwift Swi Apple le",
"2 I want a string",
"3 i want a string",
"4 I want a function to receive the above inputs and return a String",
"5 i want a function to receive the above inputs and return a String",
"6 abc aBc Abc abc ABC aabc",
"7 droid android otherdroid and android and otherdroid",
]
test.forEach { s in
let rs = parseString(s)
print("Orig:", s)
print("Ret :", rs)
print()
}
outputs this to the debug console:
Orig: 1 hello helloSwift Swi Apple le
Ret : 1-helloSwift-Apple
Orig: 2 I want a string
Ret : 2-I-want-string
Orig: 3 i want a string
Ret : 3-want-string
Orig: 4 I want a function to receive the above inputs and return a String
Ret : 4-I-want-function-to-receive-the-above-inputs-and-return-String
Orig: 5 i want a function to receive the above inputs and return a String
Ret : 5-want-function-to-receive-the-above-inputs-and-return-String
Orig: 6 abc aBc Abc abc ABC aabc
Ret : 6-aBc-Abc-ABC-aabc
Orig: 7 droid android otherdroid and android and otherdroid
Ret : 7-android-otherdroid
As you'll immediately notice, you didn't mention case-sensitivity, so we haven't addressed that... that's why examples 2 & 3 and 4 & 5 return different results:
"I" is not found in "string"
"i" is found in "string"

How to split uncode string into characters

I have strings like
"\U0aac\U0ab9\U0ac1\U0ab5\U0a9a\U0aa8",
"\U0a97\U0ac1\U0ab8\U0acd\U0ab8\U0acb",
"\U0aa6\U0abe\U0ab5\U0acb",
"\U0a96\U0a82\U0aa1"
But I want to split this strings by unicode character
I dont know hot to do. I know components seprated by function but it's no use here.
\nAny help would be apperiaciated
If the strings you're getting really contain \U characters, you need to parse them manually and extract the unicode scalar values. Something like this:
let strings = [
"\\U0aac\\U0ab9\\U0ac1\\U0ab5\\U0a9a\\U0aa8",
"\\U0a97\\U0ac1\\U0ab8\\U0acd\\U0ab8\\U0acb",
"\\U0aa6\\U0abe\\U0ab5\\U0acb",
"\\U0a96\\U0a82\\U0aa1"
]
for str in strings {
let chars = str.components(separatedBy: "\\U")
var string = ""
for ch in chars {
if let val = Int(ch, radix: 16), let uni = Unicode.Scalar(val) {
string.unicodeScalars.append(uni)
}
}
print(string)
}
You can map your array, split its elements at non hexa digit values, compact map them into UInt32 values, initializate unicode scalars with them and map the resulting elements of your array into a UnicodeScalarView and init a new string with it:
let arr = [
#"\U0aac\U0ab9\U0ac1\U0ab5\U0a9a\U0aa8"#,
#"\U0a97\U0ac1\U0ab8\U0acd\U0ab8\U0acb"#,
#"\U0aa6\U0abe\U0ab5\U0acb"#,
#"\U0a96\U0a82\U0aa1"#]
let strings = arr.map {
$0.split { !$0.isHexDigit }
.compactMap { UInt32($0, radix: 16) }
.compactMap(Unicode.Scalar.init)
}.map { String(String.UnicodeScalarView($0)) }
print(strings)
This will print
["બહુવચન", "ગુસ્સો", "દાવો", "ખંડ"]
So, the string that comes back already has the "\" because in order to use components you'd need to have an additional escaping "\" so that you'd be able to do:
var listofCodes = ["\\U0aac\\U0ab9\\U0ac1\\U0ab5\\U0a9a\\U0aa8", "\\U0aac\\U0ab9\\U0ac1\\U0ab5\\U0a9a\\U0aa8"]
var unicodeArray :[String] = []
listofCodes.forEach { string in
unicodeArray
.append(contentsOf: string.components(separatedBy: "\\"))
unicodeArray.removeAll(where: {value in value == ""})
}
print(unicodeArray)
I will revise this answer once you specify how you are obtaining these strings, as is I get a non-valid string error from the start.

How to capitalize each alternate character of a string?

Lets say there is a string "johngoestoschool" it should become "JoHnGoEsToScHoOl" and incase if there is a special character in between it should ignore it for example given string "jo$%##hn^goe!st#os&choo)l" answer should be "Jo$%##Hn^GoE!sT#oS&cHoO)l"
From this answer, we in order to iterate we can do:
let s = "alpha"
for i in s.characters.indices[s.startIndex..<s.endIndex]
{
print(s[i])
}
Why can't we print the value of "i" here?
When we do i.customPlaygroundQuickLook it types int 0 to int4.
So my idea is to
if (i.customPlaygroundQuickLook == 3) {
s.characters.currentindex = capitalized
}
Kindly help
This should solve your function, the hard part is just checking weather the character is letters or not, using inout and replace range would give better performance:
func altCaptalized(string: String) -> String {
var stringAr = string.characters.map({ String($0) }) // Convert string to characters array and mapped it to become array of single letter strings
var numOfLetters = 0
// Convert string to array of unicode scalar character to compare in CharacterSet
for (i,uni) in string.unicodeScalars.enumerated() {
//Check if the scalar character is in letter character set
if CharacterSet.letters.contains(uni) {
if numOfLetters % 2 == 0 {
stringAr[i] = stringAr[i].uppercased() //Replace lowercased letter with uppercased
}
numOfLetters += 1
}
}
return stringAr.joined() //Combine all the single letter strings in the array into one string
}

Quotation Mark Lost in Array

I have multiple strings in an array. They each already contain a quotation mark but I want to add another " to each string's end. This is how I do it:
for var str in coordinates {
str += "\""
print(str)
}
print(coordinates[0])
print(str) prints My"String" which is how it should be.
But print(coordinates[0] prints My"String
How come? Is this just how the strings are displayed but the actual string contains the "?
Thanks in advance.
In for var the var is only for the current scope inside the loop.
It's not a reference to the strings in the array, it's a copy (value).
You could mutate the existing strings in the array but the Swifty way of doing this is to create a new one, with map for example:
let result = coordinates.map { str in return str + "\"" }
Short version:
let result = coordinates.map { $0 + "\"" }

Swift - Remove " character from string

I have a string which is "Optional("5")". I need to remove the "" surrounding the 5. I have removed the 'Optional' by doing:
text2 = text2.stringByReplacingOccurrencesOfString("Optional(", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
I am having difficulties removing the " characters as they designate the end of a string in the code.
Swift uses backslash to escape double quotes. Here is the list of escaped special characters in Swift:
\0 (null character)
\\ (backslash)
\t (horizontal tab)
\n (line feed)
\r (carriage return)
\" (double quote)
\' (single quote)
This should work:
text2 = text2.replacingOccurrences(of: "\\", with: "", options: NSString.CompareOptions.literal, range: nil)
Swift 3 and Swift 4:
text2 = text2.textureName.replacingOccurrences(of: "\"", with: "", options: NSString.CompareOptions.literal, range:nil)
Latest documents updated to Swift 3.0.1 have:
Null Character (\0)
Backslash (\\)
Horizontal Tab (\t)
Line Feed (\n)
Carriage Return (\r)
Double Quote (\")
Single Quote (\')
Unicode scalar (\u{n}), where n is between one and eight hexadecimal digits
If you need more details you can take a look to the official docs here
Here is the swift 3 updated answer
var editedText = myLabel.text?.replacingOccurrences(of: "\"", with: "")
Null Character (\0)
Backslash (\\)
Horizontal Tab (\t)
Line Feed (\n)
Carriage Return (\r)
Double Quote (\")
Single Quote (\')
Unicode scalar (\u{n})
To remove the optional you only should do this
println("\(text2!)")
cause if you dont use "!" it takes the optional value of text2
And to remove "" from 5 you have to convert it to NSInteger or NSNumber easy peasy. It has "" cause its an string.
Replacing for Removing is not quite logical.
String.filter allows to iterate a string char by char and keep only true assertion.
Swift 4 & 5
var aString = "Optional(\"5\")"
aString = aString.filter { $0 != "\"" }
> Optional(5)
Or to extend
var aString = "Optional(\"5\")"
let filteredChars = "\"\n\t"
aString = aString.filter { filteredChars.range(of: String($0)) == nil }
> Optional(5)
I've eventually got this to work in the playground, having multiple characters I'm trying to remove from a string:
var otherstring = "lat\" : 40.7127837,\n"
var new = otherstring.stringByTrimmingCharactersInSet(NSCharacterSet.init(charactersInString: "la t, \n \" ':"))
count(new) //result = 10
println(new)
//yielding what I'm after just the numeric portion 40.7127837
If you want to remove more characters for example "a", "A", "b", "B", "c", "C" from string you can do it this way:
someString = someString.replacingOccurrences(of: "[abc]", with: "", options: [.regularExpression, .caseInsensitive])
As Martin R says, your string "Optional("5")" looks like you did something wrong.
dasblinkenlight answers you so it is fine, but for future readers, I will try to add alternative code as:
if let realString = yourOriginalString {
text2 = realString
} else {
text2 = ""
}
text2 in your example looks like String and it is maybe already set to "" but it looks like you have an yourOriginalString of type Optional(String) somewhere that it wasn't cast or use correctly.
I hope this can help some reader.
Swift 5 (working). Only 1 line code.
For removing single / multiple characters.
trimmingCharacters(in: CharacterSet)
In action:
var yourString:String = "(\"This Is: Your String\")"
yourString = yourString.trimmingCharacters(in: ["("," ",":","\"",")"])
print(yourString)
Output:
ThisIsYourString
You are entering a Set that contains characters you're required to trim.
Let's say you have a string:
var string = "potatoes + carrots"
And you want to replace the word "potatoes" in that string with "tomatoes"
string = string.replacingOccurrences(of: "potatoes", with: "tomatoes", options: NSString.CompareOptions.literal, range: nil)
If you print your string, it will now be: "tomatoes + carrots"
If you want to remove the word potatoes from the sting altogether, you can use:
string = string.replacingOccurrences(of: "potatoes", with: "", options: NSString.CompareOptions.literal, range: nil)
If you want to use some other characters in your sting, use:
Null Character (\0)
Backslash (\)
Horizontal Tab (\t)
Line Feed (\n)
Carriage Return (\r)
Double Quote (\")
Single Quote (\')
Example:
string = string.replacingOccurrences(of: "potatoes", with: "dog\'s toys", options: NSString.CompareOptions.literal, range: nil)
Output: "dog's toys + carrots"
If you are getting the output Optional(5) when trying to print the value of 5 in an optional Int or String, you should unwrap the value first:
if value != nil
{ print(value)
}
or you can use this:
if let value = text {
print(value)
}
or in simple just 1 line answer:
print(value ?? "")
The last line will check if variable 'value' has any value assigned to it, if not it will print empty string
You've instantiated text2 as an Optional (e.g. var text2: String?).
This is why you receive Optional("5") in your string.
take away the ? and replace with:
var text2: String = ""
If you are getting the output Optional(5) when trying to print the value of 5 in an optional Int or String, you should unwrap the value first:
if let value = text {
print(value)
}
Now you've got the value without the "Optional" string that Swift adds when the value is not unwrapped before.

Resources