Difference between Swift String Interpolation Prints - ios

I am new to iOS development, while I was going through string interpolation. I want to know the clarification between these print statement's output:
var value = "5"
print("Values is: \(value)")
print("Values is:", value)
print("Values is: " + value)
Output is : Values is: 5
Values is: 5
Values is: 5

Practically all three forms do the same thing.
The differences are
String interpolation syntax. You can put everything within the inner parentheses which responds to the CustomStringConvertible protocol.
Variadic parameter syntax. print is declared func print(_ items: Any...,. Any... means you can pass multiple items comma separated which are treated as array.
String concatenation syntax : The strings are concatenated with the + operator
If 5 was Int rather than String forms 1 and 2 are valid but not form 3

For such a question, we should take a look at print(_:separator:terminator:) parameters:
1) items: is a variadic parameter of type Any, which means that you can pass zero or more items to it. Example:
print() // passing nothing
print("Hello") // passing single item (String)
print(101, 40.45, false, ["Hi", "Greetings"]) // passing multiple items
2) separator: the string to print between each item (as mentioned in its documentation). Example:
print(101, 40.45, false, ["Hi", "Greetings"], separator: " <=> ")
// 101<=>40.45<=>false<=>["Hi", "Greetings"]
3) terminator: the string to print after all items have been printed (as mentioned in its documentation). Example:
print(101, 40.45, false, ["Hi", "Greetings"], terminator: " ==>")
// 101 40.45 false ["Hi", "Greetings"] ==>
Back to your cases:
First, keep in mind that for all of your three cases you are passing only items parameter; It is valid -for sure- because separator and terminator have default values as " " and \n.
Now, for the first and third print statements
print("Values is: \(value)")
print("Values is: " + value)
what happens is: actually you are dealing with Strings, it is not about the print itself. You can do interpolation in strings as well as using the + for concatenating strings without the print:
// interpolation:
let name = "Jack"
let greetingMessage = "Greetings, \(name)"
print(greetingMessage) // => Greetings, Jack
// concatenating:
let concatenated = "Greetings" + ", " + "Sara"
print(concatenated) // => "Greetings" + ", " + "Sara"
Which means that you are passing a single String item, regardless of doing interpolation or concatenation for it.
You could also check The + function implementation in Swift. Basically, it is an append!
The second print statement:
print("Values is:", value)
What happens here is: you are passing two items; According to the default value for separator, the output is:
Values is: 5
As:
Values is: 5
^ ^^
| ||__ item #2
item #1 |
|
default separator (" ")

In this print statement output is the same but there is different like in first statement use \(value) variable within the string data.
The second statement append data in your string value with keep one space
The third statement just concat two value (it does not keep space between two value), In this statement "+" sign used as operator overloading to concat two value
let value = "5"
print("Values is: \(value)") //use variable value within string
print("Values is:", value) //append value, with keep one space
print("Values is: " + value) //just concat two value

var value = "5"
print("Values is: (value)")
// Print the value as a part of the the string. If you use print("Values is:(value)"), it will print the output without space.
print("Values is:", value)
// you do not need to add a separate space to add the value to sting. It will automatically add the value to the string with a space.
print("Values is: " + value)
// It will show error if you use integer value "Binary operator '+' cannot be applied to operands of type 'String' and 'Int'"
otherwise it will work. And if you want to concatenate int with sting you need to do something like below:-
print("Values is: " + String(value))
// it is normal concatenate number with string
All the above will print the exact

Related

How to use split and map method?

I saw a question: Swift: Split a String into an array
And there's some code I don't understand:
let fullName = "First Last"
let fullNameArr = split(fullName.characters){$0 == " "}.map{String($0)}
fullNameArr[0] // First
fullNameArr[1] // Last
How does split() and map{} work?
You're using a syntax that won't work in Xcode7. The correct syntax should be
let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init)
Getting that out of the way let's break down that line into two pieces:
split takes
A collection of Characters representing the String's extended
grapheme clusters
-- From Xcode docs
and a closure taking a character and returning Bool - true if the character can be considered as a separator.
if this syntax is confusing try reading that:
fullNameArr = fullName.characters.split({
character in
return character == " "
})
Now, split returns an array of SubSequence objects. You want to convert them back to string to be able to print them nicely. So one way of doing it would be creating a for loop iterating over all the results of split and converting them to string, then appending to a result array, or using map method that does the same.
If you look closely at the first line, you execute map on the array and pass a closure that does something with every element of the array and writes it back.
A simple example how that works
let exampleArray = [1, 2, 3]
print(exampleArray.map {$0 * 3})
// prints [3, 6, 9]
Hope that helps!

Formatting strings in Swift

In some languages, like C# for example, you can create a string in the following way:
"String {0} formatted {1} "
And then format it with String.format by passing in the values to format.
The above declaration is good, because you don't have to know of what type its parameters are when you create the string.
I tried to find similar approach in Swift, but what I found out was something like the following format:
"String %d formatted %d"
which requires you to format the string with String(format: , parameters). This is not good because you would also have to know parameter types when declaring the string.
Is there a similar approach in Swift where I wouldn't have to know the parameter types?
Use this one:
let printfOutput = String(format:"%# %2.2d", "string", 2)
It's the same as printf or the Obj-C formatting.
You can also mix it in this way:
let parm = "string"
let printfOutput = String(format:"\(parm) %2.2d", 2)
Edit: Thanks to MartinR (he knows it all ;-)
Be careful when mixing string interpolation and formatting. String(format:"\(parm) %2.2d", 2) will crash if parm contains a percent character. In (Objective-)C, the clang compiler will warn you if a format string is not a string literal.
This gives some room for hacking:
let format = "%#"
let data = "String"
let s = String(format: "\(format)", data) // prints "String"
In contrast to Obj-C which parses the format string at compile time, Swift does not do that and just interprets it at runtime.
In Swift, types need to conform to the CustomStringConvertible protocol in order to be used inside strings. This is also a requirement for the types used in string interpolation like this:
"Integer value \(intVal) and double value \(doubleVal)"
When you understand the CustomStringConvertible, you can create your own function to fulfill your needs. The following function formats the string based on the given arguments and prints it. It uses {} as a placeholder for the argument, but you can change it to anything you want.
func printWithArgs(string: String, argumentPlaceHolder: String = "{}", args: CustomStringConvertible...) {
var formattedString = string
// Get the index of the first argument placeholder
var nextPlaceholderIndex = string.range(of: argumentPlaceHolder)
// Index of the next argument to use
var nextArgIndex = 0
// Keep replacing the next placeholder as long as there's more placeholders and more unused arguments
while nextPlaceholderIndex != nil && nextArgIndex < args.count {
// Replace the argument placeholder with the argument
formattedString = formattedString.replacingOccurrences(of: argumentPlaceHolder, with: args[nextArgIndex].description, options: .caseInsensitive, range: nextPlaceholderIndex)
// Get the next argument placeholder index
nextPlaceholderIndex = formattedString.range(of: argumentPlaceHolder)
nextArgIndex += 1
}
print(formattedString)
}
printWithArgs(string: "First arg: {}, second arg: {}, third arg: {}", args: "foo", 4.12, 100)
// Prints: First arg: foo, second arg: 4.12, third arg: 100
Using a custom implementation allows you to have more control over it and tweak its behavior. For example, if you wanted to, you could modify this code to display the same argument multiple times using placeholders like {1} and {2}, you could fill the arguments in a reversed order, etc.
For more information about string interpolation in Swift: https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID292

Concatenate String in Swift

i have an array which contains strings i.e Array
i tried to concatenate string, but i got an error as "String is not identical to UInt8"
var titleString:String! = ""
for title in array {
titleString += "\(title)"
}
To concatenate all elements of a string array, you can use the reduce method:
var string = ["this", "is", "a", "string"]
let res = string.reduce("") { $0 + $1 }
The first parameter is the initial string, which is empty, and the second is a closure, which is executed for each element in the array. The closure receives 2 parameters: the value returned at the previous step (or the initial value, if it's the 1st element), and the current element value.
More info here
Addendum I forgot to explicitly answer to your question: the concatenation doesn't work because you declared the titleString as optional - just turn into a non optional variable and it will work. If you still want to use the optional, then use forced unwrapping when doing the assignment:
titleString! += "\(title)"
Addendum 2 As suggested by #MartinR, there's another simpler way to concatenate:
join("", string)
In Swift 3, this is how you join elements of a String array:
["this", "is", "a", "string"].joined(separator: "")
Although, joined(separator:) is really geared for actually putting a separator between the strings. Reduce is still more concise:
["this", "is", "a", "string"].reduce("", +)

String literal as argument for func within println?

Is there anyway to use a string literal as an argument to a function within a println statement.
func greetings(name: String) -> String {
return "Greetings \(name)!"
}
What I was trying to do: (I tried escaping the quotes around Earthling.)
println("OUTPUT: \(greetings("Earthling"))")
You can alternatively do this:
let name = "Earthling"
println("OUTPUT: \(greetings(name))")
And this works too:
println(greetings("Earthling"))
I tried escaping the quotes in the first example but with no luck, its not super important as its only a test, I was just curious if there was a way to do this, using a function call with a string literal as an argument within a print or println statement that contains other text.
From the Apple docs:
The expressions you write inside parentheses within an interpolated
string cannot contain an unescaped double quote (") or backslash (\),
and cannot contain a carriage return or line feed.
The problem is of course not with println but with the embedding of expressions with quotes in string literals.
Thus
let b = false
let s1 = b ? "is" : "isn't"
let s2 = "it \(b ? "is" : "isn't")" // won't compile
However NSLog as a one-liner'' works quite well here
NSLog("it %#", b ? "is" : "isn't")
Note %#, not %s. Try the latter in a playground to see why.

How do I compare two characters in Dart?

I want to compare two characters. Something like this:
if ('a' > 'b')
However, the above code is comparing two strings.
How do I do this in Dart?
Dart doesn't have a 'char' or 'character' type. You can get the UTF-16 character code from any point in a string, and compare that.
Use codeUnitAt to get the actual character code from a string.
if ('a'.codeUnitAt(0) > 'b'.codeUnitAt(0))
See the codeUnitAt docs: https://api.dartlang.org/docs/channels/stable/latest/dart_core/String.html#codeUnitAt
String in Dart implements the Comparable interface. You can use compareTo to compare them.
String a = 'a';
String b = 'b';
String c = 'a';
print('value: ${a.compareTo(b)}'); // prints "value: -1"
print('value: ${a.compareTo(c)}'); // prints "value: 0"
print('value: ${b.compareTo(a)}'); // prints "value: 1"

Resources