Swift string comparison failure due to newlines - swift

I am trying to compare two strings
1. String read from a .strings file using the api, String(contentsOf: localizableFilePath, encoding: .ascii).propertyListFromStringsFileFormat()
2. Strings to be written to the strings file
The string comparison fails when there are newlines in the strings, i,e
the string 1 has newLine character in them so its like
"something
something"
and string 2 is like "something \nsomething"
and the comparison fails because of this.

You can try replacing occurrences of newline characters with an empty string: For example:
let inputString = "Something \nSomething"
let test = "Something Something"
test == inputString.replacingOccurrences(of: "\n", with: "") // true

Related

Create an NSPredicate with a line break as part of a string

I need to create a predicate that will look for the following string:
"fred\n5" where \n is a newline.
At least, this is string that is returned when reading the metadata back
You can do it with Regular Expression
let string = """
fred
5
"""
let predicate = NSPredicate(format: "self MATCHES %#", "fred\\n5")
predicate.evaluate(with: string) // true
It's also possible to use the pattern fred(\\n|\\r)5, it considers both linefeed and return.
Alternatively remove the newline character (actually any whitespace and newline characters)
let trimmedString = string.replacingOccurrences(of: "\\s", with: "", options: .regularExpression)

Regular expression in Swift

I am trying to parse a string with a regex, I am getting some problems trying to extract all the information in substrings. I am almost done, but I am stacked at this point:
For a string like this:
[00/0/00, 00:00:00] User: This is the message text and any other stuff
I can parse Date, User and Message in Swift with this code:
let line = "[00/0/00, 00:00:00] User: This is the message text and any other stuff"
let result = line.match("(.+)\\s([\\S ]*):\\s(.*\n(?:[^-]*)*|.*)$")
extension String {
func match(_ regex: String) -> [[String]] {
let nsString = self as NSString
return (try? NSRegularExpression(pattern: regex, options: []))?.matches(in: self, options: [], range: NSMakeRange(0, count)).map { match in
(0..<match.numberOfRanges).map { match.range(at: $0).location == NSNotFound ? "" : nsString.substring(with: match.range(at: $0)) }
} ?? []
}
}
The resulting array is something like this:
[["[00/0/00, 00:00:00] User: This is the message text and any other stuff","[00/0/00, 00:00:00]","User","This is the message text and any other stuff"]]
Now my problem is this, if the message has a ':' on it, the resulting array is not following the same format and breaks the parsing function.
So I think I am missing some cases in the regex, can anyone help me with this? Thanks in advance.
In the pattern, you are making use of parts that are very broad matches.
For example, .+ will first match until the end of the line, [\\S ]* will match either a non whitespace char or a space and [^-]* matches any char except a -
The reason it could potentially break is that the broad matches first match until the end of the string. As a single : is mandatory in your pattern, it will backtrack from the end of the string until it can match a : followed by a whitespace, and then tries to match the rest of the pattern.
Adding another : in the message part, may cause the backtracking to stop earlier than you would expect making the message group shorter.
You could make the pattern a bit more precise, so that the last part can also contain : without breaking the groups.
(\[[^][]*\])\s([^:]*):\s(.*)$
(\[[^][]*\]) Match the part from an opening till closing square bracket [...] in group 1
\s Match a whitespace char
([^:]*): Match any char except : in group 2, then match the expected :
\s(.*) Match a whitespace char, and capture 0+ times any char in group 3
$ End of string
Regex demo

How to replace a substring with a link(http) in swift 3?

I have a string and substring(http) and I want to replace that substring but I don't know when that substring will end. I mean want to check it until one space is not coming and after that I want to replace it.
I am checking that if my string contains http which is also a string then I want to replace it when space will come.
Here below is my example :-
let string = "Hello.World everything is good http://www.google.com By the way its good".
This is my string It can be dynamic also I mean in this above string http is there, so I want to replace "http://www.google.com" to "website".
So it would be
string = "Hello.World everything is good website By the way its good"
A possible solution is Regular Expression
The pattern searches for http:// or https:// followed one or more non-whitespace characters up to a word boundary.
let string = "Hello.World everything is good http://www.google.com By the way its good"
let trimmedString = string.replacingOccurrences(of: "https?://\\S+\\b", with: "website", options: .regularExpression)
print(trimmedString)
Split each words, replace and join back should solve this.
// split into array
let arr = string.components(separatedBy: " ")
// do checking and join
let newStr = arr.map { word in
return word.hasPrefix("http") ? "website" : word
}.joined(separator: " ")
print(newStr)

Print String using variadic params without comma, newline and brackets in Swift

While I was trying to use Swift's String(format: format, args) method, I found out that I cannot print the formatted string directly without newline(\n) and brackets being added.
So for example, I have a code like this:
func someFunc(string: String...) {
print(String(format: "test %#", string))
}
let string = "string1"
someFunc(string, "string2")
the result would be:
"test (\n string1,\n string2\n)\n"
However, I intend to deliver the result like this:
"test string1 string2"
How can I make the brackets and \n not being printed?
Since string parameter is a sequence, you can use joinWithSeparator on it, like this:
func someFunc(string: String...) {
print(string.joinWithSeparator(" "))
}
someFunc("quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog")
You will first need to concatenate your list of input strings, otherwise it will print as a list, hence the commas and parentheses. You can additionally strip out the newline characters and whitespace from the ends of the string using a character set.
var stringConcat : String = ''
for stringEntry in string {
stringConcat += stringEntry.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
Then just print out the stringConcat.

Remove last punctuation of a swift string

I'm trying to remove the last punctuation of a string in swift 2.0
var str: String = "This is a string, but i need to remove this comma, \n"
var trimmedstr: String = str.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
First I'm removing the the white spaces and newline characters at the end, and then I need to check of the last character of trimmedstr if it is a punctuation. It can be a period, comma, dash, etc, and if it is i need to remove it it.
How can i accomplish this?
There are multiple ways to do it. You can use contains to check if the last character is in the set of expected characters, and use dropLast() on the String to construct a new string without the last character:
let str = "This is a string, but i need to remove this comma, \n"
let trimmedstr = str.trimmingCharacters(in: .whitespacesAndNewlines)
if let lastchar = trimmedstr.last {
if [",", ".", "-", "?"].contains(lastchar) {
let newstr = String(trimmedstr.dropLast())
print(newstr)
}
}
Could use .trimmingCharacters(in:.whitespacesAndNewlines) and .trimmingCharacters(in: .punctuationCharacters)
for example, to remove whitespaces and punctuations on both ends of the String-
let str = "\n This is a string, but i need to remove this comma and whitespaces, \t\n"
let trimmedStr = str.trimmingCharacters(in:
.whitespacesAndNewlines).trimmingCharacters(in: .punctuationCharacters)
Result -
This is a string, but i need to remove this comma and whitespaces