Swift : how to add separators to a String at not fixed intervals only when matching conditions? - swift

So I have this portion of code :
stringName = "\(param1)\(param2)\(param3)\(param4)\(param5)"
All these params are calculated inside the function in which the stringName is being called.
What I wanna do is output the string name with all these params separated by say a coma, which in theory would be just as easy as separating them by a coma inside the string, however I want the coma to appear only between these params when they exist and they won't all exist in every case.
Because the function I'm creating depends on an array and these params on the array length, so in some cases the returned string will be :
stringName = "param1,param4"
or
stringName = "param2,param3,param5"
etc...
(got a maximum of 8 of these params)
So as sometimes these params end up being empty strings, I don't wanna end up with a string name only made of comas, just want my comas to appear inbetween 2 params when they're not empty strings.
Any idea how to format that ??
Thanks !

Assuming param1,...,param5 are all String, non-Optional, you can write something like this:
let param1: String = ""
let param2: String = "value2"
let param3: String = "value3"
let param4: String = ""
let param5: String = "value5"
let stringName = [param1, param2, param3, param4, param5]
.filter {!$0.isEmpty}
.joined(separator: ",")
print(stringName) //->value2,value3,value5

You can put all your paramXs in an array, filter out the empty ones, and used joined(separator:) to join them:
stringName = [param1, param2, param3, param4, param5, param6, param7, param8]
.filter { !$0.isEmpty }.joined(separator: ",")
An even better way of doing this would be not use 8 different variables, and rewrite your method so that it uses an array from the very beginning.

Related

Swift remove array brackets and double quotes

In my scenario, I have array of string value, I need to remove array bracket and double quotes like below, how to achieve this?
I tried below code
let selectedTeamMemberID = membersData.filter{$0.isSelected}.map{$0.userid}
let intArray = selectedTeamMemberID.map { Int($0 ?? "")!}
print("\(intArray)")
Expected output
["1","2","3"] change to 1,2,3
If you don't want to include objects without a userId you can filter on that property as well and force unwrap it. This avoids "empty" elements in the result
let selected = membersData.filter{$0.isSelected && $0.userid != nil}.map {$0.userid!}.joined(separator: ",")
But maybe more efficient and a cleaner solution is to use compactMap that maps and also filters out nil values
let selected = membersData.filter{$0.isSelected}.compactMap {$0.userid}.joined(separator: ",")
Try this out
You can Join an array of string with inbuilt method joined
let selectedTeamMemberID = membersData.filter{$0.isSelected}.map{$0.userid}
let output = selectedTeamMemberID.joined(separator: ",")
As you are printing the array , it prints the string representation.
You need to iterate over the array and print the contents
intArray.forEach{print($0, terminator: ",")}
We can add Joined after data mapping
let selectedID = membersData.filter{$0.isSelected}.map{($0.userid ?? "")}.joined(separator: ",") // ["1","2","3"] to 1,2,3
You can do it this way:
selectedTeamMemberID.joined(separator: ",")
:)

Cannot convert value of type Substring to expected argument type String - Swift 4

Trying to get substring of String and append it to array of Strings:
var stringToSplit = "TEST TEXT"
var s = [String]()
let subStr = anotherString[0 ..< 6]
s.append(subStr) // <---- HERE I GET THE ERROR
As #Leo Dabus mentioned, you need to initialize a new String with your substring:
Change:
s.append(subStr)
To:
s.append(String(subStr))
my two cents for serro in different context.
I was trying to get an array of "String" splitting a string.
"split" gives back "Substring", for efficiency reason (as per Swift.org litre).
So I ended up doing:
let buffer = "one,two,three"
let rows = buffer.split(separator:",")
let realStrings = rows.map { subString -> String in
return String(subString)
}
print(realStrings)
Ape can help someone else.

String convert to Int and replace comma to Plus sign

Using Swift, I'm trying to take a list of numbers input in a text view in an app and create a sum of this list by extracting each number for a grade calculator. Also the amount of values put in by the user changes each time. An example is shown below:
String of: 98,99,97,96...
Trying to get: 98+99+97+96...
Please Help!
Thanks
Use components(separatedBy:) to break up the comma-separated string.
Use trimmingCharacters(in:) to remove spaces before and after each element
Use Int() to convert each element into an integer.
Use compactMap (previously called flatMap) to remove any items that couldn't be converted to Int.
Use reduce to sum up the array of Int.
let input = " 98 ,99 , 97, 96 "
let values = input.components(separatedBy: ",").compactMap { Int($0.trimmingCharacters(in: .whitespaces)) }
let sum = values.reduce(0, +)
print(sum) // 390
For Swift 3 and Swift 4.
Simple way: Hard coded. Only useful if you know the exact amount of integers coming up, wanting to get calculated and printed/used further on.
let string98: String = "98"
let string99: String = "99"
let string100: String = "100"
let string101: String = "101"
let int98: Int = Int(string98)!
let int99: Int = Int(string99)!
let int100: Int = Int(string100)!
let int101: Int = Int(string101)!
// optional chaining (if or guard) instead of "!" recommended. therefore option b is better
let finalInt: Int = int98 + int99 + int100 + int101
print(finalInt) // prints Optional(398) (optional)
Fancy way as a function: Generic way. Here you can put as many strings in as you need in the end. You could, for example, gather all the strings first and then use the array to have them calculated.
func getCalculatedIntegerFrom(strings: [String]) -> Int {
var result = Int()
for element in strings {
guard let int = Int(element) else {
break // or return nil
// break instead of return, returns Integer of all
// the values it was able to turn into Integer
// so even if there is a String f.e. "123S", it would
// still return an Integer instead of nil
// if you want to use return, you have to set "-> Int?" as optional
}
result = result + int
}
return result
}
let arrayOfStrings = ["98", "99", "100", "101"]
let result = getCalculatedIntegerFrom(strings: arrayOfStrings)
print(result) // prints 398 (non-optional)
let myString = "556"
let myInt = Int(myString)

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.

Interpolate String Loaded From File

I can't figure out how to load a string from a file and have variables referenced in that string be interpolated.
Let's say a text file at filePath that has these contents:
Hello there, \(name)!
I can load this file into a string with:
let string = String.stringWithContentsOfFile(filePath, encoding: NSUTF8StringEncoding, error: nil)!
In my class, I have loaded a name in: let name = "George"
I'd like this new string to interpolate the \(name) using my constant, so that its value is Hello there, George!. (In reality the text file is a much larger template with lots of strings that need to be swapped in.)
I see String has a convertFromStringInterpolation method but I can't figure out if that's the right way to do this. Does anyone have any ideas?
This cannot be done as you intend, because it goes against type safety at compile time (the compiler cannot check type safety on the variables that you are trying to refer to on the string file).
As a workaround, you can manually define a replacement table, as follows:
// Extend String to conform to the Printable protocol
extension String: Printable
{
public var description: String { return self }
}
var string = "Hello there, [firstName] [lastName]. You are [height]cm tall and [age] years old!"
let firstName = "John"
let lastName = "Appleseed"
let age = 33
let height = 1.74
let tokenTable: [String: Printable] = [
"[firstName]": firstName,
"[lastName]": lastName,
"[age]": age,
"[height]": height]
for (token, value) in tokenTable
{
string = string.stringByReplacingOccurrencesOfString(token, withString: value.description)
}
println(string)
// Prints: "Hello there, John Appleseed. You are 1.74cm tall and 33 years old!"
You can store entities of any type as the values of tokenTable, as long as they conform to the Printable protocol.
To automate things further, you could define the tokenTable constant in a separate Swift file, and auto-generate that file by using a separate script to extract the tokens from your string-containing file.
Note that this approach will probably be quite inefficient with very large string files (but not much more inefficient than reading the whole string into memory on the first place). If that is a problem, consider processing the string file in a buffered way.
There is no built in mechanism for doing this, you will have to create your own.
Here is an example of a VERY rudimentary version:
var values = [
"name": "George"
]
var textFromFile = "Hello there, <name>!"
var parts = split(textFromFile, {$0 == "<" || $0 == ">"}, maxSplit: 10, allowEmptySlices: true)
var output = ""
for index in 0 ..< parts.count {
if index % 2 == 0 {
// If it is even, it is not a variable
output += parts[index]
}
else {
// If it is odd, it is a variable so look it up
if let value = values[parts[index]] {
output += value
}
else {
output += "NOT_FOUND"
}
}
}
println(output) // "Hello there, George!"
Depending on your use case, you will probably have to make this much more robust.