Swift - optional String vs. implicitly unwrapped optional String [duplicate] - string

This question already has answers here:
Swift variable decorations with "?" (question mark) and "!" (exclamation mark)
(1 answer)
What does an exclamation mark mean in the Swift language?
(23 answers)
Closed 7 years ago.
I was reading the Swift book published by Apple. According to the book:
var possibleString: String? = "an optional string"
var assumedString: String! = "an implicitly unwrapped optional string"
what's the difference between these two? And when should each one be used? It turns out both can even be set to nil.

Introduce another variable into your code:
var string: String
And then observe:
string = possibleString
The code above will fail with:
Value of optional type 'String?' not unwrapped, did you mean to use '!' or '?'?
However:
string = assumedString
works.
assumedString is automatically, or implicitly unwrapped for you. Use implicitly unwrapped optionals where you are certain that the optional contains a value.

use the first one when you cannot guaranty that there will be a string value when accessing the parameter.
use the second when you are 100% sure that there is a string value in this parameter when accessing it: for example, a username field parsing before sending it to validation on the server side, when you disable the login button press if this field is empty. so it means that if the login button was pressed, you have a string value in the text field, so it is guarantied to NOT to be nil.
p.s. in swift 2, use let and not var if your value will not be changed later...

From Apples Swift programming guide:
var possibleString: String? = "an optional string"
Optional is value is either contains a value or nil value to indicate the that the value is missing.
While using you have to use if and let together, as
var newString : String
if let possibleString = possibleString {
newString = possibleString
}
2.
var assumedString: String! = "an implicitly unwrapped optional string"
An implicitly unwrapped optional is similar to optional types but we can use it like a non optional value each time when it is accessed.
In this case you can use it directly as
var newString : String
newString = possibleString

Related

Cant iterate over vec<&str> and pass element into option_env!()? [duplicate]

This question already has answers here:
println! error: expected a literal / format argument must be a string literal
(4 answers)
What does the word "literal" mean?
(11 answers)
Closed last month.
Sorry if this is a noob question.
I've created a .cargo/config.toml file in my project and configured some env variables like so:
[env]
GAME_ZERO_LEVEL = "0"
GAME_ZERO_MULTIPLIER = "0.1"
GAME_ONE_LEVEL = "1"
GAME_ONE_MULTIPLIER = "1.0"
GAME_TWO_LEVEL = "2"
GAME_TWO_MULTIPLIER = "2.5"
GAME_THREE_LEVEL = "3"
GAME_THREE_MULTIPLIER = "5.0"
GAME_FOUR_LEVEL = "4"
GAME_FOUR_MULTIPLIER = "10.0"
I will parse these into u32 and f32.
Anyway, I'm able to fetch these individually with
let value = option_env!("GAME_ZERO_LEVEL").unwrap();
Here is the problem, I want to fetch all env variables in a loop like so:
let env_keys: Vec<&str> = vec![
"GAME_ZERO_LEVEL",
"GAME_ZERO_MULTIPLIER",
"GAME_ONE_LEVEL",
"GAME_ONE_MULTIPLIER",
"GAME_TWO_LEVEL",
"GAME_TWO_MULTIPLIER",
"GAME_THREE_LEVEL",
"GAME_THREE_MULTIPLIER",
"GAME_FOUR_LEVEL",
"GAME_FOUR_MULTIPLIER",
];
env_keys.iter().for_each(|key| {
let value = option_env!(key).unwrap(); //error here
// do some stuff with it
}
But I get the following compile error
rustc: argument must be a string literal
Safe to say, Im pretty confused as my previous understanding was that &str are string literals, and that passing in a &str in a variable doesnt't work. Any help understanding this would be much appreciated!
Note: I cant use std::env::{var, vars}
Slight misconception there &str or more specifically &'static stris the type of string literals but string literals are just the ones you type literally like this: "this is a string literal", or this r"I'm a raw string literal" or even like this r#"I'm a raw string literal which can contain " wherever"#. Everything else is not a literal. Things that are not string literals also can have that type though.
Compare also string literals in Rust by example and the reference
option_env!() evaluates it's contents at compile time so you can't use it with runtime variables like your key.

How to check whether a string contains a substring in Kotlin?

Example:
String1 = "AbBaCca";
String2 = "bac";
I want to perform a check that String1 contains String2 or not.
Kotlin has stdlib package to perform certain extension function operation over the string, you can check this method it will check the substring in a string, you can ignore the case by passing true/false value. Refer this link
"AbBaCca".contains("bac", ignoreCase = true)
The most idiomatic way to check this is to use the in operator:
String2 in String1
This is equivalent to calling contains(), but shorter and more readable.
You can do it by using the "in" - operator, e.g.
val url : String = "http://www.google.de"
val check : Boolean = "http" in url
check has the value true then. :)
See the contains method in the documentation.
String1.contains(String2);
Kotlin has a few different contains function on Strings, see here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/contains.html.
If you want it to be true that string2 is contained in string1 (ie you want to ignore case), they even have a convenient boolean argument for you, so you won't need to convert to lowercase first.
For anyone out there like me who wanted to do this for a nullable String, that is, String?, here is my solution:
operator fun String?.contains(substring:String): Boolean {
return if (this is String) {
// Need to convert to CharSequence, otherwise keeps calling my
// contains in an endless loop.
val charSequence: CharSequence = this
charSequence.contains(substring)
} else {
false
}
}
// Uses Kotlin convention of converting 'in' to operator 'contains'
if (shortString in nullableLongString) {
// TODO: Your stuff goes here!
}

Swift 3.0 String concatenation leaves "Optional" [duplicate]

This question already has an answer here:
Swift 3 incorrect string interpolation with implicitly unwrapped Optionals
(1 answer)
Closed 6 years ago.
Since Swift 3.0 I have some troubles with Strings, especially with concatenation. 1st example would be what I used since I started using Swift to define my url strings.
internal let host: String! = "https://host.io/"
let urlString = "\(host)oauth/access_token"
where host is defined as at the beginning of the class. This worked perfectly until Swift 3.0, now that prints out like this:
Optional("https://host.io/")oauth/access_token
which is very strange. Now I have to write this
let urlString = host + "oauth/access_token"
To get the expected output.
https://host.io/oauth/access_token
Another - I guess similar problem I'm having with Strings is this. I'm again concatenating strings but this time I'm using + ilke with urlString - but this time that doesn't work. Line of code looks like this:
self.labelName.text = currentUser.name + " " + String(describing: ageComponents.year)
which unfortunately produces string like this: "My Name Optional(26)". In this case I don't have a solution String(describing: ageComponents.year) is not an optional and it doesn't allow me to do things like String(describing: ageComponents.year) ?? "whatever"
Anyone seen something similar?
In Swift 3 all properties of the native struct DateComponents are optionals unlike the Foundation NSDateComponents counterparts.
var year: Int? { get set }
You need to unwrap it. If you specified the unit year in ageComponents you can do that safely.

How can I modify individual characters in a String using Swift?

var str: String = "sometext"
for i in str.characters.indices
{
str[i] = "c"
}
print(str)
I'm getting the following error:
error: cannot assign through subscript: subscript is get-only
You are getting this error because the subscript method of a Swift String is get-only like it is saying in your warning.
This is different from an Array.
Array:
array[0] ✅
array[0] = 0 ✅
String:
str[0] ❌
str[0] = "0" ❌
str[str.startIndex.advancedBy(0)] ✅
Use replaceRange for accomplishing your task.
Example:
var value = "green red blue"
value.replaceRange(value.startIndex.advancedBy(
6)..<value.startIndex.advancedBy(6 + 3),
with: "yellow")
print(value)
Result:
green yellow blue
Also have a look at this superb blog article from Ole Begemann who explains how Swift Strings work very detailed. You will also find the answer why you can't use subscript methods on Swift Strings.
Because of the way Swift strings are stored, the String type does not support random access to its Characters via an integer index — there is no direct equivalent to NSStringʼs characterAtIndex: method. Conceptually, a String can be seen as a doubly linked list of characters rather than an array.
Article Link
In some cases it may be preferable to convert the String to an Array, mutate, then convert back to a String, e.g.:
var chars = Array("sometext".characters)
for i in 0..<chars.count {
chars[i] = "c"
}
let string = String(chars)
Advantages include:
clarity
better performance on large strings: O(1) time for making each replacement in Array vs O(N) time for making each replacement in String.
Disadvantages include:
higher memory consumption: O(N) for Array vs O(1) for String.
Pick your poison :)

How to extract substring in Groovy?

I have a Groovy method that currently works but is real ugly/hacky looking:
def parseId(String str) {
System.out.println("str: " + str)
int index = href.indexOf("repositoryId")
System.out.println("index: " + index)
int repoIndex = index + 13
System.out.println("repoIndex" + repoIndex)
String repoId = href.substring(repoIndex)
System.out.println("repoId is: " + repoId)
}
When this runs, you might get output like:
str: wsodk3oke30d30kdl4kof94j93jr94f3kd03k043k?planKey=si23j383&repositoryId=31850514
index: 59
repoIndex: 72
repoId is: 31850514
As you can see, I'm simply interested in obtaining the repositoryId value (everything after the = operator) out of the String. Is there a more efficient/Groovier way of doing this or this the only way?
There are a lot of ways to achieve what you want. I'll suggest a simple one using split:
sub = { it.split("repositoryId=")[1] }
str='wsodk3oke30d30kdl4kof94j93jr94f3kd03k043k?planKey=si23j383&repositoryId=31850514'
assert sub(str) == '31850514'
Using a regular expression you could do
def repositoryId = (str =~ "repositoryId=(.*)")[0][1]
The =~ is a regex matcher
or a shortcut regexp - if you are looking only for single match:
String repoId = str.replaceFirst( /.*&repositoryId=(\w+).*/, '$1' )
All the answers here contains regular expressions, however there are a bunch of string methods in Groovy.
String Function
Sample
Description
contains
myStringVar.contains(substring)
Returns true if and only if this string contains the specified sequence of char values
equals
myStringVar.equals(substring)
This is similar to the above but has to be an exact match for the check to return a true value
endsWith
myStringVar.endsWith(suffix)
This method checks the new value contains an ending string
startsWith
myStringVar.startsWith(prefix)
This method checks the new value contains an starting string
equalsIgnoreCase
myStringVar.equalsIgnoreCase(substring)
The same as equals but without case sensitivity
isEmpty
myStringVar.isEmpty()
Checks if myStringVar is populated or not.
matches
myStringVar.matches(substring)
This is the same as equals with the slight difference being that matches takes a regular string as a parameter unlike equals which takes another String object
replace
myStringVar.replace(old,new)
Returns a string resulting from replacing all occurrences of oldChar in this string with newChar
replaceAll
myStringVar.replaceAll(old_regex,new)
Replaces each substring of this string that matches the given regular expression with the given replacement
split
myStringVar.split(regex)
Splits this string around matches of the given regular expression
Source

Resources