Dictionary won't let me append a string to its values - ios

I'm trying to create a function which takes an array of names, and sorts it in a dictionary with letters and names as keys and values. But now the dictionary wont let me append the string to the values. My code looks like this:
func listCounter(usernames: [String])->Dictionary <String,[String]> {
var dict=Dictionary<String,[String]>()
var letterList = [String]()
for user in usernames{
var index = user.substringToIndex(advance(user.startIndex,1))
index = index.lowercaseString as String
if find(letterList, index) != 0{
dict[index] += [user]
}else{
dict[index] = [user]
letterList += [index]
}
}
return dict
}
The error comes in the line where I'm trying to add the new string to the dictionary, it says: "Cannot invoke '+=' with an argument list of type '$T4,$T6'" which is telling me there's something wrong with the types, but I don't know how to fix it.
Any suggestions on how to solve this would be appreciated.

That happens because a dictionary lookup always returns an optional - since the preceding if should ensure that the element exists, you can safely apply the forced unwrapping operator on that:
dict[index]! += [user]
However running a test on a playground resulted in a runtime exception - I think this condition:
if find(letterList, index) != 0 {
is not reliable.
I replaced with an explicit check for the key existence, and it worked:
if dict[index] != nil {
dict[index]! += [user]
Note: I didn't use optional binding like this:
if var element = dict[index] {
element += [user]
because arrays are value types, copied by value. Assigning the array to a variable actually creates a copy of it, so the addition is done on the copy, leaving the original array unchanged.

if find(letterList, index) != 0 { ... }
should actually be
if find(letterList, index) != nil { ... }
or just
if contains(letterList, index) { ... }
But #Antonio has already explained the error message and given a solution. As an alternative, you can also take advantage of
optional chaining:
for user in usernames {
var index = user.substringToIndex(advance(user.startIndex,1))
index = index.lowercaseString as String
if (dict[index]?.append(user)) == nil {
dict[index] = [user]
letterList.append(index)
}
}
How does it work? If dict[index] is nil, then
dict[index]?.append(user)
does nothing and returns nil, so that the if-block is executed.
Otherwise
dict[index]?.append(user)
appends the user to the array in dict[index] and the if-block
is not executed.
You could also write it as a one-liner, using the "nil-coalescing operator" ??:
for user in usernames {
var index = user.substringToIndex(advance(user.startIndex,1))
index = index.lowercaseString as String
dict[index] = (dict[index] ?? []) + [user]
}
Here, dict[index] ?? [] evaluates to the dictionary value if that
already exists, and to an empty array otherwise. And the array
of all indices can also be computed after the loop with
letterList = Array(dict.keys)

Related

find the minimum index of a repeating element in the array Swift

I dont know how doint that. I try find replacement obj method
indexOfObject on the swift but not find
i have array = [1,3,6,2,3] and input in array value 3, i am need find repeating value with min index from array. Answer with index 1. How do it?
You have to loop through the entire collection, for each item, see if we had seen this before. And as we are doing that, let’s keep track of the index of the first item that has been repeated somewhere in the collection, to see if this is the first repeated item or not:
extension Collection where Element: Hashable {
func indexOfFirstRepeated() -> Index? {
var result: Index? // the index of the first item repeated anywhere else in the collection
var firstOccurrences: [Element: Index] = [:] // dictionary to keep track of the first item that every element was first encountered in the collection
for (index, element) in zip(indices, self) {
if let firstOccurrence = firstOccurrences[element] { // find previous occurrence of this value, if any
if let previousLowestIndex = result { // if we found this element before, let's see if we had already found another repeated element
if firstOccurrence < previousLowestIndex { // if so, let’s see if the first occurrence of this element occurred before the first occurrence of the previously discovered repeated element
result = firstOccurrence
}
} else { // otherwise, no prior repeated element found, so this is our first repeated element found thus far
result = firstOccurrence
}
} else {
firstOccurrences[element] = index // if we got here, this is the first time we've seen this element, so record the index of this first occurrence
}
}
return result
}
}
Thus:
let array = [9,8,7,1,3,6,2,3,1]
if let index = array.indexOfFirstRepeated() {
print(index) // 3
}
Now, obviously, as we iterate through this array, the value 3 is the first value that we will see repeated, but that doesn’t matter, because the repeated value 1 will be found at the very end of the array, and 1’s first index is lower than 3’s first index.
Two observations on the above:
I made it generic, so that it works on any hashable type, e.g.:
let array = ["bill", "sam", "susan", "sam", "bill"]
if let index = array.indexOfFirstRepeated() {
print(index)
} else {
print("not found")
}
I made this a Collection extension (rather than an Array extension) so that it would work on other collection types (e.g. array slices, etc.). You can make it an Array extension, just as easily, but we prefer to use the most abstract type that is convenient, to make it as flexible as possible.
This is basically a riff on uniqued.
import Algorithms
public extension BidirectionalCollection where Element: Hashable {
var firstDuplicate: (index: Index, element: Element)? {
var set: Set<Element> = []
return indexed().reversed().reduce(into: nil) {
if !set.insert($1.element).inserted {
$0 = $1
}
}
}
}
You can get the last duplicate by not reversing before reducing.
Assume you have an array of n integers, with a[i] = i, except that a[1] = a[2] = 1, and I may or may not have have changed a[i] = 0 for some i >= 2.
The smallest index of a duplicate element is either 0 or 1. To find out which you have to find the i >= 2 with a[i] = 0 or find that no such i exists. So you have to visit all array elements.

Determine "nil" value in JSON

The app receives JSON object from the server. And some field in the object can be missing, or be nil. So, I need to find them before computing a value. I have a code fragment as below:
print(package["store"]!["cover"]) //here, console output: "nil"
if ((package["store"]!["cover"]) != nil) {
//the 'if' statment above has no effect, statment below is executed,
// and error occurs.
imageName = STATIC_IMAGE_URL + (package["cover"] as! String)
}
How can I detect if the response JSON has some missing or nil fields?
You can use optional chaining, optional binding, and conditional casting combined in the same if-let statement:
if let cover = package["store"]?["cover"] as? String {
imageName = STATIC_IMAGE_URL + cover
} else {
imageName = "someDefaultImage"
}
It works like this:
package["store"]?["cover"] will return nil if either package["store"], or package["store"]["cover"] is nil
the conditional cast as? String returns nil if the expression to the left is not a String
finally the if-let construct will either populate cover with the actual string, or will go on the else branch if there's no match

How to check if a UILabel is empty and append content to a label?

New to ios and swift. Want some best practice tips.
I want to append content to a label in a new line. My try:
#IBOutlet weak var history: UILabel!
#IBAction func appendContent() {
if history.text != nil && !history.text!.isEmpty {
history.text = history.text! + "\r\n" + "some content"
}
else{
history.text = digit
}
}
It seems to work, however,
Is there a better way to check the text is not nil and not empty?
Is there a "keyword" thing for "\r\n"?
You can use optional binding: if let to check if something is nil.
Example 1:
if let text = history.text where !text.isEmpty {
history.text! += "\ncontent"
} else {
history.text = digit
}
Or you can use map to check for optionals:
Example 2:
history.text = history.text.map { !$0.isEmpty ? $0 + "\ncontent" : digit } ?? digit
!$0.isEmpty is in most cases not even needed so the code can look a bit better:
history.text = history.text.map { $0 + "\ncontent" } ?? digit
EDIT: What does map do:
The map method solves the problem of transforming the elements of an array using a function.
Let’s say we have an array of Ints representing some sums of money and we want to create a new array of strings that contains the money value followed by the “€” character i.e. [10,20,45,32] -> ["10€","20€","45€","32€"].
The ugly way of doing this is by creating a new empty array, iterating our original array transforming each element and adding it to the new array
var stringsArray = [String]()
for money in moneyArray {
stringsArray += "\(money)€"
}
Using map is just:
let stringsArray = moneyArray.map { "\($0)€" }
It can also be used for optionals:
The existing map allows you to apply a function to the value inside an optional, if that optional is non-nil. For example, suppose you have an optional integer i and you want to double it. You could write i.map { $0 * 2 }. If i has a value, you get back an optional of that value doubled. On the other hand, if i is nil, no doubling takes place.
(source)
What does ?? do:
The nil coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.
The nil coalescing operator is shorthand for the code below:
a != nil ? a! : b
What about using something like this:
if let text = history.text where !text.isEmpty {
history.text = "\(text)\nsome content"
}

iterating though two arrays to output values

So I have two arrays a name array and a values array they are a string and double respectively. I want to be able for a user to type in a textfield and to iterate though the name array until there is a match then output the value that has the same number as the name to be outputted
this is the code i have:
for(var i = 0; i<name.count; i++){
if name[i] == typeFood{
yieldOutput == percent[i]
}
}
First, use find to locate the location of the value in the name array, then use the returned index to look up the percent:
if let idx = find(name, typeFood) {
yieldOutput = percent[idx]
}
You can also combine the two actions together with map to declare an output variable using let:
if let foodPercentage = find(name, typeFood).map({ percent[$0] }) {
// foodPercentage will have a value here
}
else {
// not-found logic here
}

When should I compare an optional value to nil?

Quite often, you need to write code such as the following:
if someOptional != nil {
// do something with the unwrapped someOptional e.g.
someFunction(someOptional!)
}
This seems a bit verbose, and also I hear that using the ! force unwrap operator can be unsafe and best avoided. Is there a better way to handle this?
It is almost always unnecessary to check if an optional is not nil. Pretty much the only time you need to do this is if its nil-ness is the only thing you want to know about – you don’t care what’s in the value, just that it’s not nil.
Under most other circumstances, there is a bit of Swift shorthand that can more safely and concisely do the task inside the if for you.
Using the value if it isn’t nil
Instead of:
let s = "1"
let i = Int(s)
if i != nil {
print(i! + 1)
}
you can use if let:
if let i = Int(s) {
print(i + 1)
}
You can also use var:
if var i = Int(s) {
print(++i) // prints 2
}
but note that i will be a local copy - any changes to i will not affect the value inside the original optional.
You can unwrap multiple optionals within a single if let, and later ones can depend on earlier ones:
if let url = NSURL(string: urlString),
data = NSData(contentsOfURL: url),
image = UIImage(data: data)
{
let view = UIImageView(image: image)
// etc.
}
You can also add where clauses to the unwrapped values:
if let url = NSURL(string: urlString) where url.pathExtension == "png",
let data = NSData(contentsOfURL: url), image = UIImage(data: data)
{ etc. }
Replacing nil with a default
Instead of:
let j: Int
if i != nil {
j = i
}
else {
j = 0
}
or:
let j = i != nil ? i! : 0
you can use the nil-coalescing operator, ??:
// j will be the unwrapped value of i,
// or 0 if i is nil
let j = i ?? 0
Equating an optional with a non-optional
Instead of:
if i != nil && i! == 2 {
print("i is two and not nil")
}
you can check if optionals are equal to non-optional values:
if i == 2 {
print("i is two and not nil")
}
This also works with comparisons:
if i < 5 { }
nil is always equal to other nils, and is less than any non-nil value.
Be careful! There can be gotchas here:
let a: Any = "hello"
let b: Any = "goodbye"
if (a as? Double) == (b as? Double) {
print("these will be equal because both nil...")
}
Calling a method (or reading a property) on an optional
Instead of:
let j: Int
if i != nil {
j = i.successor()
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional chaining, ?.:
let j = i?.successor()
Note, j will also now be optional, to account for the fatalError scenario. Later, you can use one of the other techniques in this answer to handle j’s optionality, but you can often defer actually unwrapping your optionals until much later, or sometimes not at all.
As the name implies, you can chain them, so you can write:
let j = s.toInt()?.successor()?.successor()
Optional chaining also works with subscripts:
let dictOfArrays: ["nine": [0,1,2,3,4,5,6,7]]
let sevenOfNine = dictOfArrays["nine"]?[7] // returns {Some 7}
and functions:
let dictOfFuncs: [String:(Int,Int)->Int] = [
"add":(+),
"subtract":(-)
]
dictOfFuncs["add"]?(1,1) // returns {Some 2}
Assigning to a property on an optional
Instead of:
if splitViewController != nil {
splitViewController!.delegate = self
}
you can assign through an optional chain:
splitViewController?.delegate = self
Only if splitViewController is non-nil will the assignment happen.
Using the value if it isn’t nil, or bailing (new in Swift 2.0)
Sometimes in a function, there’s a short bit of code you want to write to check an optional, and if it’s nil, exit the function early, otherwise keep going.
You might write this like this:
func f(s: String) {
let i = Int(s)
if i == nil { fatalError("Input must be a number") }
print(i! + 1)
}
or to avoid the force unwrap, like this:
func f(s: String) {
if let i = Int(s) {
print(i! + 1)
}
else {
fatalErrr("Input must be a number")
}
}
but it’s much nicer to keep the error-handling code at the top by the check. This can also lead to unpleasant nesting (the "pyramid of doom").
Instead you can use guard, which is like an if not let:
func f(s: String) {
guard let i = Int(s)
else { fatalError("Input must be a number") }
// i will be an non-optional Int
print(i+1)
}
The else part must exit the scope of the guarded value, e.g. a return or fatalError, to guarantee that the guarded value will be valid for the remainder of the scope.
guard isn’t limited to function scope. For example the following:
var a = ["0","1","foo","2"]
while !a.isEmpty {
guard let i = Int(a.removeLast())
else { continue }
print(i+1, appendNewline: false)
}
prints 321.
Looping over non-nil items in a sequence (new in Swift 2.0)
If you have a sequence of optionals, you can use for case let _? to iterate over all the non-optional elements:
let a = ["0","1","foo","2"]
for case let i? in a.map({ Int($0)}) {
print(i+1, appendNewline: false)
}
prints 321. This is using the pattern-matching syntax for an optional, which is a variable name followed by ?.
You can also use this pattern matching in switch statements:
func add(i: Int?, _ j: Int?) -> Int? {
switch (i,j) {
case (nil,nil), (_?,nil), (nil,_?):
return nil
case let (x?,y?):
return x + y
}
}
add(1,2) // 3
add(nil, 1) // nil
Looping until a function returns nil
Much like if let, you can also write while let and loop until nil:
while let line = readLine() {
print(line)
}
You can also write while var (similar caveats to if var apply).
where clauses also work here (and terminate the loop, rather than skipping):
while let line = readLine()
where !line.isEmpty {
print(line)
}
Passing an optional into a function that takes a non-optional and returns a result
Instead of:
let j: Int
if i != nil {
j = abs(i!)
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional’s map operator:
let j = i.map { abs($0) }
This is very similar to optional chaining, but for when you need to pass the non-optional value into the function as an argument. As with optional chaining, the result will be optional.
This is nice when you want an optional anyway. For example, reduce1 is like reduce, but uses the first value as the seed, returning an optional in case the array is empty. You might write it like this (using the guard keyword from earlier):
extension Array {
func reduce1(combine: (T,T)->T)->T? {
guard let head = self.first
else { return nil }
return dropFirst(self).reduce(head, combine: combine)
}
}
[1,2,3].reduce1(+) // returns 6
But instead you could map the .first property, and return that:
extension Array {
func reduce1(combine: (T,T)->T)->T? {
return self.first.map {
dropFirst(self).reduce($0, combine: combine)
}
}
}
Passing an optional into a function that takes an optional and returns a result, avoiding annoying double-optionals
Sometimes, you want something similar to map, but the function you want to call itself returns an optional. For example:
// an array of arrays
let arr = [[1,2,3],[4,5,6]]
// .first returns an optional of the first element of the array
// (optional because the array could be empty, in which case it's nil)
let fst = arr.first // fst is now [Int]?, an optional array of ints
// now, if we want to find the index of the value 2, we could use map and find
let idx = fst.map { find($0, 2) }
But now idx is of type Int??, a double-optional. Instead, you can use flatMap, which “flattens” the result into a single optional:
let idx = fst.flatMap { find($0, 2) }
// idx will be of type Int?
// and not Int?? unlike if `map` was used
I think you should go back to the Swift programming book and learn what these things are for. ! is used when you are absolutely sure that the optional isn't nil. Since you declared that you are absolutely sure, it crashes if you're wrong. Which is entirely intentional. It is "unsafe and best avoided" in the sense that asserts in your code are "unsafe and best avoided". For example:
if someOptional != nil {
someFunction(someOptional!)
}
The ! is absolutely safe. Unless there is a big blunder in your code, like writing by mistake (I hope you spot the bug)
if someOptional != nil {
someFunction(SomeOptional!)
}
in which case your app may crash, you investigate why it crashes, and you fix the bug - which is exactly what the crash is there for. One goal in Swift is that obviously your app should work correctly, but since Swift cannot enforce this, it enforces that your app either works correctly or crashes if possible, so bugs get removed before the app ships.
You there is one way. It is called Optional Chaining. From documentation:
Optional chaining is a process for querying and calling properties,
methods, and subscripts on an optional that might currently be nil. If
the optional contains a value, the property, method, or subscript call
succeeds; if the optional is nil, the property, method, or subscript
call returns nil. Multiple queries can be chained together, and the
entire chain fails gracefully if any link in the chain is nil.
Here is some example
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."
You can check the full article here.
We can use optional binding.
var x:Int?
if let y = x {
// x was not nil, and its value is now stored in y
}
else {
// x was nil
}
After lot of thinking and researching i have came up with the easiest way to unwrap an optional :
Create a new Swift File and name it UnwrapOperator.swift
Paste the following code in the file :
import Foundation
import UIKit
protocol OptionalType { init() }
extension String: OptionalType {}
extension Int: OptionalType {}
extension Int64: OptionalType {}
extension Float: OptionalType {}
extension Double: OptionalType {}
extension CGFloat: OptionalType {}
extension Bool: OptionalType {}
extension UIImage : OptionalType {}
extension IndexPath : OptionalType {}
extension NSNumber : OptionalType {}
extension Date : OptionalType {}
extension UIViewController : OptionalType {}
postfix operator *?
postfix func *?<T: OptionalType>( lhs: T?) -> T {
guard let validLhs = lhs else { return T() }
return validLhs
}
prefix operator /
prefix func /<T: OptionalType>( rhs: T?) -> T {
guard let validRhs = rhs else { return T() }
return validRhs
}
Now the above code has created 2 operator [One prefix and one postfix].
At the time of unwrapping you can use either of these operator before or after the optionals
The explanation is simple, the operators returns the constructor value if they get nil in variable else the contained value inside the variable.
Below is the example of usage :
var a_optional : String? = "abc"
var b_optional : Int? = 123
// before the usage of Operators
print(a_optional) --> Optional("abc")
print(b_optional) --> Optional(123)
// Prefix Operator Usage
print(/a_optional) --> "abc"
print(/b_optional) --> 123
// Postfix Operator Usage
print(a_optional*?) --> "abc"
print(b_optional*?) --> 123
Below is the example when variable contains nil :
var a_optional : String? = nil
var b_optional : Int? = nil
// before the usage of Operators
print(a_optional) --> nil
print(b_optional) --> nil
// Prefix Operator Usage
print(/a_optional) --> ""
print(/b_optional) --> 0
// Postfix Operator Usage
print(a_optional*?) --> ""
print(b_optional*?) --> 0
Now it is your choice which operator you use, both serve the same purpose.

Resources