Swift 2D array with different types - arrays

Is it possible to have a multi-dimentional array that has more than one data type.
Example (I want the last item to be an Int):
var london = [[String]]()
london[0] = ["England", "Chelmsford", 49]
london[1] = ["Wales", "Cardiff", 212]
london[2] = ["Scotland", "Glasgow", 556]
london[3] = ["Germany", "Frankfurt", 640]

I think you are better off with an array of struct or Dictionary:
struct CityInfo {
var country : String
var city : String
var data : Int
}
var london = [CityInfo]()
london.append(CityInfo(country: "England", city: "Chelmsford", data: 49))
london.append(CityInfo(country: "Wales", city: "Cardiff", data: 212))
london.append(CityInfo(country: "Scotland", city: "Glasgow", data: 556))
london.append(CityInfo(country: "Germany", city: "Frankfurt", data: 640))
But you can use 2D array if you want:
var london = [[Any]]()
london.append(["England", "Chelmsford", 49])
london.append(["Wales", "Cardiff", 212])
london.append(["Scotland", "Glasgow", 556])
london.append(["Germany", "Frankfurt", 640])

You use an array with in that array one of 2 options
either make it a class or struct containing the country/city/integer as properties
or
use a tuple
typealias myData = (country: String, city: String, myNumber:Integer)
what use depends on what you'll do with it in your code

If you really want it like how you have it, just use AnyObject as the type
var london = [[AnyObject]]()
london.append(["England", "Chelmsford", 49])
london.append(["Wales", "Cardiff", 212])
london.append(["Scotland", "Glasgow", 556])
london.append(["Germany", "Frankfurt", 640])

Related

Swift - Check if a value belongs is in an array

I have an array of type "User" and I would like to check if a value belongs to a property type.
My code :
struct User: Identifiable {
var id = UUID()
var name: String
var age: String
}
var array: User = [
User[name: "AZE", age: "10"]
User[name: "QSD", age: "37"]
]
For example I'd like to know if "AZE" belongs to the property array "name". What is the function for retrieving this information. I hope you understood my problem and thank you for your answer.
First of all, arrays define with [Type] like [User]
Second of all init method calls as with (Arguments) like User(name: ,age:)
And last but not least, don't forget the ',' between elements of the array.
So
struct User: Identifiable {
var id = UUID()
var name: String
var age: String
}
var array: [User] = [
User(name: "AZE", age: "10"),
User(name: "QSD", age: "37")
]
So now you can check your element inside with contains like
array.contains(where: { user in user.name == "AZE" }) // returns `true` if it is
Tips
Try name arrays not array. Use plural names instead like users
To returtning the found one:
users.first(where: { user in user.name == "AZE" })
To summarizing it
users.first { $0.name == "AZE" }

Newbie: referencing and initializing structure elements within structures

OK, super-newbie Swift learner here with what I am sure is a simple question, that for some reason I cannot wrap my head around.
In the below code, I am creating a (very) simple address book structure just to understand how to reference and initialize the various elements, especially structures within structures. What am I doing wrong and is there a better way to write this? I am getting errors (using Swift Playground).
Errors on the last three lines:
Instance member 'page' cannot be used on the type 'AddressBookStruct'
Instance member 'subscript' cannot be used on type '[AddressPageStruct]'.
Plus, when I set var page = [AddressBookStrcut] I get the error:
Expected member name or constructor call after type name
Thanks in advance for the understanding nudge. :)
struct AddressPageStruct {
let firstName: String
let lastName: String
let cellPhone: Int
init(f: String, l:String, c:Int) {
firstName = f
lastName = l
cellPhone = c
}
}
struct AddressBookStruct {
let color: String
let size: String
var page = [AddressPageStruct]
}
var littleBlackBook = AddressBookStruct.self
littleBlackBook.init(color: "Black", size: "Little")
littleBlackBook.page[0].cellPhone = 6191234567
littleBlackBook.page[0].firstName = "Bob"
littleBlackBook.page[0].lastName = "Smith"
The struct is value type, please check this.
structure vs class in swift language,
you can't make this littleBlackBook.page[0].cellPhone, because cellPhone is constant you use let, instead use the constructor, also I change the page for empty array of AddressPageStruct
import Cocoa
struct AddressPageStruct {
let firstName: String
let lastName: String
let cellPhone: Int
init(f: String, l:String, c:Int) {
firstName = f
lastName = l
cellPhone = c
}
}
struct AddressBookStruct {
let color: String
let size: String
var page = [AddressPageStruct]()
}
var littleBlackBook = AddressBookStruct(color: "Black", size: "Little")
littleBlackBook.page.append(AddressPageStruct(f: "Bob", l: "Smith", c: 6191234567))
print(littleBlackBook.page)
enter code here
var littleBlackBook = AddressBookStruct(color: "Black", size: "Little")
let item = AddressPageStruct(f: "Bob", l: "Smith", c:6191234567 )
littleBlackBook.page.append(item)
littleBlackBook.page.append(AddressPageStruct(f: "Joe", l: "Blog", c: 3123467))
print(littleBlackBook.page[0])
print(littleBlackBook.page[1])
print(littleBlackBook)

Sort array of dictionaries where key is unknown

I have an array of dictionaries of type [[String:SchoolModel]]. The keys are the id of the school and then the school model contains info about the school like its name for example. I want to sort this array by SchoolModel.name, but can't figure out how since my key is a unique id for every element in the array.
struct SchoolModel {
var name: String
var city: String
var state: String
}
You can access the first value of each dictionary iterated to get the name.
struct SchoolModel {
var name: String
var city: String
var state: String
}
let schools: [[String:SchoolModel]] = [
["1": SchoolModel(name: "1", city: "a", state: "x")],
["2": SchoolModel(name: "2", city: "b", state: "y")],
["3": SchoolModel(name: "3", city: "c", state: "z")]
]
print(schools.sorted {
guard
let a = $0.values.first?.name,
let b = $1.values.first?.name else { return false }
return a < b
})
However, you should consider adding an id property to your struct. You can make it optional so you can still initiate a SchoolModel that hasn't been created yet.
struct SchoolModel {
var id: String?
var name: String
var city: String
var state: String
}
Then where ever you are populating the array of dictionaries, append the SchoolModel object without embedding it inside a dictionary, resulting in an array of type [SchoolModel].

Make a copy of object with same address in swift

var empObj : EmployeeModel!
var tempObj : EmployeeModel!
tempObj = empObj.copy() as! EmployeeModel
whenevr I am copy the empObj to tempObj it's memory address is changed.I want to prevent this any idea?
when you copy its actually making a new reference. instead of copying just assign the value . then both will share the same reference
var empObj : EmployeeModel!
var tempObj = empObj
When you want the same address for different values
USE =
for eg.
var ogArray : NSMutableArray()
var tempArray = ogArray
If you are using objects two variables can point at the same object so that changing one changes them both, whereas if you tried that with structs you'd find that Swift creates a full copy so that changing the copy does not affect the original.
If you want to modify copies of a class object so that modifying one object doesn't have an effect on anything else, you can use NSCopying.
Make your class conform to NSCopying. This isn't strictly required
Implement the method copy(with:), where the actual copying happens.
Call copy() on your object.
Example Code for NSCopying
class Person: NSObject, NSCopying {
var firstName: String
var lastName: String
var age: Int
init(firstName: String, lastName: String, age: Int) {
self.firstName = firstName
self.lastName = lastName
self.age = age
}
func copy(with zone: NSZone? = nil) -> Any {
let copy = Person(firstName: firstName, lastName: lastName, age: age)
return copy
}
}
Check the output of this code in Playground
let paul = Person(firstName: "Paul", lastName: "Hudson", age: 36)
let sophie = paul.copy() as! Person
sophie.firstName = "Sophie"
sophie.age = 6
print("\(paul.firstName) \(paul.lastName) is \(paul.age)")
print("\(sophie.firstName) \(sophie.lastName) is \(sophie.age)")
Reference

How to print variables in structs in arrays?

With this Swift 3.0 lines:
struct Person {
var name: String
var surname: String
var phone: Int
var isCustomer: Bool
}
var contacts: [Person] = []
contacts.append(Person(name: "Jack", surname: "Johnson", phone: 2, isCustomer: false))
contacts.append(Person(name: "Mike", surname: "Morris", phone: 3, isCustomer: true))
I have created an array that includes two structures which include 4 variables each.
I can print a single object of the array like this: print(contacts[0].name)
but is there any way to print all the Strings of the name section at once?
Learn how to use map. I use it all the time.
print(contacts.map({ $0.name }))
Search for map in this Apple Documentation about Closures
You'll have to iterate over the array, either printing the values as you go, or capturing them into a string and printing them all at once.
Here's one way:
for contact in contacts {
print(contact.name)
}
Here's another:
contacts.forEach { print($0.name) }
Finally, you could join all the strings into one value with a separator and just print once. When you do it this way the joinWithSeparator function iterates the array for you:
let names = contacts.map { $0.name }
let joinedNames = names.joinWithSeparator(" ")
print(joinedNames)
You should implement the protocol CustomStringConvertible by defining the computed property description:
struct Person: CustomStringConvertible {
var name: String
var surname: String
var phone: Int
var isCustomer: Bool
var description: String {
return
"Name: \(name)\n" +
"Surname: \(surname)\n" +
"Phone: \(phone)\n" +
"Is Customer? \(isCustomer)\n"
}
}
And then:
var contacts: [Person] = []
contacts.append(Person(name: "Jack", surname: "Johnson", phone: 2, isCustomer: false))
contacts.append(Person(name: "Mike", surname: "Morris", phone: 3, isCustomer: true))
print(contacts)
Obviously you can define description as you want.

Resources