Swift: Declaring empty tuples - ios

What's the correct way to declare an empty tuple?
For Arrays: var myArr : [String] = []
For tuples: var myTuple: (key: String, val: Int) = () ?
Is there a correct way to achieve this?

There's no such thing as an "unfilled" tuple value. In other words you don't create an empty tuple and then add values to it later. It's important to remember that tuples aren't collections like Array or Dictionary. Tuples are structured types. For example, you can't iterate through a tuple with a for loop. In your example, myTuple is a single value that happens to contain a String and an Int.
A tuple is like an on-demand unnamed structure, such as the following struct but if it were possible for it to be unnamed:
struct MyStruct {
let key: String
let val: Int
}
If you want to model a missing tuple value, you should make the type of the entire tuple optional. For example:
var myTuple: (key: String, val: Int)? = nil

Related

Sorting Array returns a Dictionary

I have the following object:
private var datasource: [Int: [MyCustomModel]] = [:]
At a later stage, I need to sort the datasource by the key property (ascending).
I do it as follows:
let sorted = datasource.sorted(by: {$0.key < $1.key})
This does sort the content by the key (Int) value perfectly, though I cannot set the datasource to the sorted property.
Xcode presents the following error
Cannot assign value of type '[Dictionary<Int, [MyCustomModel]>.Element]' (aka 'Array<(key: Int, value: Array)>') to type '[Int : [MyCustomModel]]'
I get that the returned type, after sorting is a Dictionary and not an Array.
How can I overcome this issue?
Thanks.
I didn't get any solution for the same to sort the dictionary, but you can do something like below.
Its works for me.
make structure of key and value.
struct STRUCT_TEMP
{
var key : Int
var value : [MyCustomModel]
}
create structure variable.
var structTemp : [STRUCT_TEMP] = []
convert your dictionary in structure like below:
self.structTemp = datasource.map({ STRUCT_TEMP(key: $0.key, value: $0.value) })
now you can do anything with the structTemp array. Like sorting, filter and you can also use this array everywhere you want instead of dictionary.
let datasource: [Int: [MyCustomModel]] = [:]
Dictionaries cannot be sorted!. If you use sorted(by: { $0.key < $1.key}) to sort the datasource, the result is an array, not a dictionary.
datasource.sorted(by: { $0.key < $1.key})
Swift 5.5
You can use OrderedDictionary. It keeps insertion order.
https://www.advancedswift.com/ordereddictionary/

How do we append values to dictionary containing 3 elements in swift 2.3?

I am trying to append value to dictionary which I have declared like this.
var setHomIconDict:[(iconImg: UIImage, Operator: String, oprCode: String, oprMerchCode:String)]!
I am not sure its dictionary though. I am learning swift and I found a Intresting code on net. Anyway I am confused on how will I append values to this. I tried
setHomIconDict.append((iconImg:img!, Operator: "Strin", oprCode: "Hello", oprMerchCode: "Huja"))
But i get this error : fatal error: unexpectedly found nil while unwrapping an Optional value . here is the image
Can anyone suggest an appropriate way.
setHomIconDict is not Dictionary it is an Array of tuple and you are getting this crash because you haven't initialized the setHomIconDict object, you have just declared its type. So initialized it with its declaration.
var setHomIconDict:[(iconImg: UIImage, Operator: String, oprCode: String, oprMerchCode:String)] = []
Note: Instead of creating array of tuple better solution is to create one custom model Class with the property that you want to set/access, then create array of that custom Class objects and use it.
You are probably better off creating a struct to hold your values. Then your array would be an array of that struct.
struct homIcon {
var iconImg: UIImage
var Operator: String
var oprCode: String
var oprMerchCode:String
}
var setHomIconArray:[homIcon] = []
let newHomIcon = homIcon(iconImg: img!, Operator: "Strin", oprCode: "Hello", oprMerchCode: "Huja")
setHomIconArray.append(newHomIcon)
As Nirav says, the syntax you are using creates an array of tuples. If you want a dictionary get rid of the parentheses.
You want to define key/value pairs using this syntax:
var aDict = [key:value, key:value, key:value]
Then you can add new key/value pairs using:
aDict[newKey] = newValue
Is your goal to create and use a dictionary, or is it your goal to user and understand the structure that you found on the net?

let array behavior in Swift 2.1

I am befuddled by the current array behavior in Swift 2.1. I have read the docs and many posts (which could be out-of-date) and am no closer to understanding.
Here's my code for separating a deck of cards into wildCards and non-wildcards:
let wildCards : [Card] = []
let nonWildCards : [NonJoker] = []
Meld.sortAndSeparateWildCards(wildCardRank, cards: self.cards, nonWildCards: nonWildCards, wildCards: wildCards)
...
static func sortAndSeparateWildCards(wildCardRank : Rank, var cards : [Card], var nonWildCards : [NonJoker], var wildCards : [Card]) {
//cards contains the list to be sorted
if cards.isEmpty {return}
nonWildCards.removeAll()
wildCards.removeAll()
for card in cards {
if (card.isWildCard(wildCardRank)!) {wildCards.append(card)}
else {nonWildCards.append(card as! NonJoker)}
}
cards = nonWildCards.sort(NonJoker.cardComparatorRankFirstDesc)
cards += wildCards
}
What I don't understand:
Xcode insists that I should change wildCards and nonWildCards to let constants, even though I am mutating the arrays by adding values to them (many of the posts I have read say that let behavior prevents adding to or removing elements from an Array)
I originally had these arrays passed as inout variables, because I thought that Arrays were passed by value and not by reference (the docs suggest that they are treated this way; see the bottom of this page https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID82)
EDIT: I thought the code was working, but I was confused.
Corrected code, per the answer below, with the bad behavior that isEmpty returns nil.
var wildCards : [Card] = []
var nonWildCards : [NonJoker] = []
Meld.sortAndSeparateWildCards(wildCardRank, cards: &self.cards, nonWildCards: &nonWildCards, wildCards: &wildCards)
...
static func sortAndSeparateWildCards(wildCardRank : Rank, inout cards : [Card], inout nonWildCards : [NonJoker], inout wildCards : [Card]) {
//cards contains the list to be sorted
if cards.isEmpty {return}
nonWildCards.removeAll()
wildCards.removeAll()
for card in cards {
if (card.isWildCard(wildCardRank)!) {wildCards.append(card)}
else {nonWildCards.append(card as! NonJoker)}
}
cards = nonWildCards.sort(NonJoker.cardComparatorRankFirstDesc)
cards += wildCards
}
Arrays are structs in Swift. In the way you've done it, the changes are not persisted out of the method. If you want to alter them in a function, you need to mark them as var in the declaration, and pass their pointer when calling the function. So something like this:
var wildCards = [Card]()
var nonWildCards = [NonJoker]()
static func sortAndSeparateWildCards(wildCardRank : Rank, inout cards : [Card], inout nonWildCards : [NonJoker], inout wildCards : [Card]) {}
Meld.sortAndSeparateWildCards(wildCardRank, cards: &self.cards, nonWildCards: &nonWildCards, wildCards: &wildCards)
You were right when assuming that arrays were being passed by value and not by reference. In Swift, arrays are value types - they are structs - which means that if you want to modify their contents, you need to declare them as var.
Now var has a broader meaning, and if it's applied to function arguments, it allows you to mutate those arguments within the function. However, keep in mind that you are mutating a copy of the array that was passed as argument.
So, in order for the changes that you apply to an array within a function be visible to the caller of that function, you need to declare the parameters as inout, which passes them by reference instead of value.

Removing a value at a specified index of a dictionary swift

I am writing a function that deletes a search from an apps NSUserDefaults. The method removes the deleted search from the searches Dictionary. I am confused about the syntax of this function. I don't understand how we access the value of the searches Dictionary with the searches[tags[index]]. To access the value at that index of the searches Dictionary wouldn't we just say searches[index] ?
private var searches: Dictionary <String, String> = [:] // stores tag-query pairs
private var tags: Array<String> = [] // stores tags in user-specified order
// returns the query String for the taga at a given index
func queryForTagAtIndex(index: Int) -> String? {
return searches[tags[index]]
}
Since your dictionary is of the type [String:String] to access or add a value to it, the key should be of type String and not Int. index is of Type Int. So it will give an error if we do return searches[index]. And since tags is of type String, we can use that as the key for the searches.
Here are some links that will help you : https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
https://developer.apple.com/library/ios/documentation/General/Reference/SwiftStandardLibraryReference/Dictionary.html
And I would edit the code for readability purposes to this :
private var searches:[String:String]=[String:String]() // stores tag-query pairs
private var tags:[String] = [String]() // stores tags in user-specified order
// returns the query String for the taga at a given index
func queryForTagAtIndex(index: Int) -> String? {
return searches[tags[index]]
}

Tuple vs Dictionary differences

Can someone please explain what the major differences there are between Tuples and Dictionaries are and when to use which in Swift?
Major difference:
If you need to return multiple values from a method you can use tuple.
Tuple won't need any key value pairs like Dictionary.
A tuple can contain only the predefined number of values, in dictionary there is no such limitation.
A tuple can contain different values with different datatype while a dictionary can contain only one datatype value at a time
Tuples are particularly useful for returning multiple values from a function. A dictionary can be used as a model object.
There are two types of Tuple:
1 Named Tuple
In Named tuple we assign individual names to each elements.
Define it like:
let nameAndAge = (name:"Midhun", age:7)
Access the values like:
nameAndAge.name
nameAndAge.age
2 Unnamed Tuple
In unnamed tuple we don't specify the name for it's elements.
Define it like:
let nameAndAge = ("Midhun", 7)
Access the values like:
nameAndAge.0
nameAndAge.1
or
let (theName, thAge) = nameAndAge
theName
thAge
Reference:
Tuple
Tuples enable you to create and pass around groupings of values. You
can use a tuple to return multiple values from a function as a single
compound value.
You can check more about Tuple in Swift Programming Language
Dictionary
A dictionary is a container that stores multiple values of the same
type. Each value is associated with a unique key, which acts as an
identifier for that value within the dictionary
You can check more about Dictionary in Swift CollectionTypes
A tuple is completely predefined: it can only have the names and number of values you've predefined for it, though they can be different value types, and they don't have to have names. And the names are literals.
A dictionary can have any number of key-value pairs, of one value type. And the keys can be referred to through variables.
Here's a tuple (with names):
typealias MySillyTuple = (theInt:Int, theString:String)
That's it. There is one Int called theInt, one String called theString, and that is exactly what it must have, no more, no less. And the only way to access the values by name is as a literal: t.theInt. If you have a string "theInt", you can't use it to access t.theInt.
Here's a Dictionary:
var d = [String:String]()
Now d can have any number of keys, and any keys, from none to a gazillion. And the keys can be specified using string variables; you don't have to know in advance what a key will be. And all the values must be strings.
So basically I would say a tuple is nothing like a dictionary. A dictionary is a complex beast for look up by dynamic keys. A tuple is just a value that is more than one value.
Dictionary is Collection Type, Tuple is Compound type.
Dictionary is Key Value type, Tuple is Comma separated list of multiple types
Dictionary:
var dictionary = ["keyone": "value one", "keytwo": "Value Two"]
Tuple:
let someTuple: (Double, Double, String, (Int, Int)) = (3.14159, 2.71828, "Hello", (2, 3))
A dictionary is made up of key-value sets. A tuple is made for passing grouped values.
Dictionaries:
A dictionary is a container that stores multiple values of the same
type. Each value is associated with a unique key, which acts as an
identifier for that value within the dictionary.
A dictionary should be used for creating lists of associated objects. An example use would be a dictionary of players and their scores:
var scoreDictionary = ["Alice" : 100, "Bob" : 700]
Tuples:
Tuples group multiple values into a single compound value.
A tuple should be used for passing groups of values. They are similar to arrays, but are fixed-length and immutable. An example use might be a tuple representing a 3-dimensional point:
var myPoint = (10, 12, 14)
As you can see there are many cases in which you would use a dictionary and many cases in which you would use a tuple. Each has its own specific purpose.
Tuples are compound values, and can be useful for functions returning several values from a function. e.g. (from the Apple Docs):
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
This function returns a tuple containing min, max and sum. These values can be accessed either by name or position:
let statistics = calculateStatistics([5, 3, 100, 3, 9])
var sum:Int = statistics.sum
var sum2:Int = statistics.2
Dictionaries are "lookup" data types. They return an object for a given key. For example the following code:
let font:NSFont = NSFont(name: "AppleCasual", size: 18.0)!
let textStyle = NSMutableParagraphStyle.defaultParagraphStyle().mutableCopy() as NSMutableParagraphStyle
textStyle.alignment = NSTextAlignment.LeftTextAlignment
let textColor:NSColor = NSColor(calibratedRed: 1.0, green: 0.0, blue: 1.0, alpha: 1.0)
let attribs = [NSFontAttributeName: font,
NSForegroundColorAttributeName: textColor,
NSParagraphStyleAttributeName: textStyle]
let color = attribs[NSForegroundColorAttributeName]
println("color = \(color)")
Will print:
color = Optional(NSCalibratedRGBColorSpace 1 0 1 1)
Dictionaries are useful for many things and are required for some functions. For example (after the code above):
let testString:NSString = "test String"
var img:NSImage = NSImage(size: NSMakeSize(200,200))
img.lockFocus()
testString.drawAtPoint(NSMakePoint(0.0, 0.0), withAttributes: attribs)
img.unlockFocus()
In this code drawAtPoint uses the dictionary attribs to lookup the parameters it needs. The parameters don't need to be in any specific order because drawAtPoint will lookup the values it needs by using the correct key.
Dictionaries and tuples are similar, but not quite the same. In the code above the dictionary returned an Optional type:Optional(NSCalibratedRGBColorSpace 1 0 1 1)
If we use a tuple for the same purpose:
var attribTuple = (font:NSFont(name: "AppleCasual", size: 18.0), color:NSColor(calibratedRed: 1.0, green: 0.0, blue: 1.0, alpha: 1.0))
println("tupleColor = \(attribTuple.color)")
Prints:
tupleColor = NSCalibratedRGBColorSpace 1 0 1 1
Not the optional type the dictionary did.
Tuples are fixed-length things. You can’t add an extra element to a tuple or remove one. Once you create a tuple it has the same number of elements – var t = (1,2) is of type (Int,Int). It can never become (1,2,3), the most you could do is change it to, say, (7,8). This is all fixed at compile-time.
You can access the elements via their numeric positions like this
t.0 + t.1 // with (1,2), would equal 3
t.0 = 7
Arrays are variable length: you can start with an array var a = [1,2], and then add an entry via a.append(3) to make it [1,2,3]. You can tell how many items with a.count. You can access/update elements via a subscript: a[0] + a[2] // equals 4
You can name the elements in tuples:
var n = (foo: 1, bar: 2)
Then you can use those names:
n.foo + n.bar // equals 3
This doesn’t remove the ability to access them by position though:
n.0 + n.1 // equals 3
But these names, once set, are fixed at compile time just like the length:
n.blarg // will fail to compile
This is not the same as dictionaries, which (like arrays), can grow or shrink:
var d = [“foo”:1, “bar”:2]
d[“baz”] = 3;
d[“blarg”] // returns nil at runtime, there’s no such element

Resources