Build an array based on another class Constructor - arrays

I want to create an array of Custom types in Swift based on another class. How can I pass the array count to the Shop class constructor below?
(count of customer array should be cnt in Shop class init)
class Customer {
var id:Int
var name:String
var balance:Double=500
init(Id:Int,Name:String, Balance: Double) {
id=Id
name=Name
balance=Balance
}
}
class Shop {
let cus:[Customer]
init(cnt:Int) {
//
}
}

I am not sure what is the exact problem. From what I understood, you are simply trying to do something like this:
let customers = [Customer]()
customers.append(Customer(Id: 1, Name: "Mike", Balance: 100))
customers.append(Customer(Id: 2, Name: "Sara", Balance: 150))
customers.append(Customer(Id: 3, Name: "Dan", Balance: 120))
let shop = Shop(cnt: customers.count)
Edit: Based on your comment, you seem to want to populate the cus array in the Shop class based on the passed parameter to the constructor. Which is a weird decision because you want to create an array of a class with multiple properties (Id, Name, Balance) knowing only the count. What data will go to these properties?
I will assume you want to create a fake array of arbitrary Customer class.
class Shop {
var cus: [Customer]
init(cnt: Int) {
cus = [Customer]()
for i in 0..<cnt {
cus.append(Customer(Id: i, Name: "name_\(i)", Balance: Double(i*100)))
}
}
}

Related

How do you create main-category/subcategory data model in swift?

I'm creating a budget app and I'm new to programming.
I want to create an interface similar to the Apple Reminders app.
The first view is a list of main categories.
When you tap on a main category, the list of subcategories will appear.
I'm not sure whether to use a class or struct.
Here's how the code looks in my mind:
struct Category {
let mainCategories: [String] = [
"Income",
"Housing",
"Transportation",
"Food",
...
]
let incomeSubCategory: [String] = [
"Salary",
"Bonus",
"Rental Income",
...
]
let housingSubCategory: [String] = [
"Mortgage/Rent",
"Property Tax",
"Homeowner's Insurance",
...
]
}
Am I going about this the right way? Or should I be using classes for inheritance?
Thanks.
EDIT:
I've tried using enums, but the data seems to be less flexible and accessible than structs.
Is it possible to make SubCategory a struct array within Category?
Like this:
struct Category {
var name: String
var color: UIColor
var amount: Double
var subCategories: [SubCategory]
}
struct SubCategory {
var name: String
var amount: Double
}
let categories = [
Category(
name: "Income",
color: UIColor(rgb: Constants.green), subCategories: [name: "Paycheck", amount: 2500.00])
]
Structs are probably fine. Nothing you've described needs inheritance and you don't seem to be modifying the information.
What I would suggest is to keep related information together. With that in mind, I would do something like:
struct Category {
var name: String
var subCategories: [String]
}
let categories = [Category(name: "Income", subCategories: ["Salary", "Bonus", "Rental Income"]),
Category(name: "Housing", subCategories: ["Mortgage/Rent", "Property Tax", "Homeowner's Insurance"])]
The advantage here is that, when you select a category, its related subcategories are implicitly available...no extra work to determine which ones match.
Use Enums instead of struct/class.
enum MainCategory: String, CaseIterable {
case income, housing //...
}
enum IncomeSubCategory: String, CaseIterable {
case salary, bonus //...
}
enum HousingSubCategory: String, CaseIterable {
case rent, tax //...
}
The CaseIterable protocol conformance allows you to have the allCases array in case you need it to iterate over the values one by one. Like this:
MainCategory.allCases.forEach { print($0) }

Create an object array from another object array and reconstruct the original object array later using map

Consider the following classes
class Category {
var tag: String?
var itemList: [Item]?
}
class Item {
var id: Int?
var type: String?
var itemDetails: ItemDetails?
}
class ItemDetails {
var description: String?
var name: String?
var price: Float?
}
Given an array of Category objects.
var categoryList: [Category]
I want to create a new object array by extracting only the name in ItemDetails(inorder to apply a filter) and an id inorder to reconstruct back array of Category objects.
Hence, I have to reconstruct the array of Category objects
from new object array.
How to do both extraction and reconstruction using the map feature?
Below are the examples of other data sources:
Datasource 1 :
var categoryList: [Category], where name need to be extracted
Datasource 2 :
var searchList = [SearchItem], where title to be extracted.
Class SearchItem {
var id: Int?
var details: SearchItemDetails?
var type: String?
}
Class SearchItemDetails {
var description: String?
var title: String?
}
DataSource 3
var products: [Products], where title to be extracted.
Class Products {
var id: Int?
var details: ProductDetails?
var type: String?
}
class ProductDetails {
var description: String?
var title: String?
}
To get an array of just the names, you do the map like you mentioned:
let categories: [Category] = ... // this already exists
let itemNames = categories.map { $0.itemList?.map({ $0.itemDetails?.name }) }
But this will preserve optionals. If you don't want optionals, then use compactMap instead.
Reconstructing, however, doesn't really make any sense. Are you using the ID to hit a database or network service? That's the only possible way you'd be able to reconstruct the original array of Categorys. Why not just hold onto the original array?

How to print elements of one class using variable of another class?

I have created two classes a Person class and a food class. Now i am making list of all the food items consumed in a year by a particular person. I want to print all of them separated by commas
Here's my code
class Food {
let name: String
var EatenBy: Person?
init(name: String){
self.name = name
}
}
And my Person class is as follows
class Person {
var name: String
var foods: [Food] = []
lazy var foodNames: () -> String = {
return ""
}
init(name: String){
self.name = name
}
func adopt(food: Food){
foods.append(food)
food.EatenBy = self
}
}
Now i want to create different food items using the Food class and then assign it to a person who have consumed them and store it in an array foods.
var person = Person(name: "Test")
var pasta = Food(name: "pasta")
Can anyone help me out how can i use the objects created using Food class and assign it to a object created in the Person class and append them in the foods array ?
My final aim is to print all the elements in the foods array separating them using commas or spaces or such, which i guess can be easily done by looping each of the element through a for loop ?
Using a Person instance, you can access its properties (including the foods array by the dot syntax: person.foods.
For printing the food names, you should declare foodNames as a computed property. As its return value, just use map to get the names of each Food instance, then use [String].joined(separator: ",") to join the contents of the array of Strings into a single String.
class Person {
var name: String
var foods: [Food] = []
var foodNames:String {
return foods.map{$0.name}.joined(separator: ",")
}
init(name: String){
self.name = name
}
func adopt(food: Food){
foods.append(food)
food.EatenBy = self
}
}
class Food {
let name: String
var EatenBy: Person?
init(name: String){
self.name = name
}
}
let john = Person(name: "John")
let pasta = Food(name: "pasta")
john.foods = [pasta, Food(name: "tuna")] //assign an array to the variable directly
john.foods.append(Food(name: "tomato")) //or append the existing array
john.adopt(food: Food(name: "bread")) //you can also use your _adopt_ function to add an element to the _foods_ array of a _Person_ instance
john.foodNames // "pasta, tuna, tomato,bread"
It looks like you are missing some basic concepts of how Swift works (like using the dot syntax to access class properties), so I would recommend reading The Swift Programming Language Guide as a start, it is a really useful starting point for a beginner Swift developer.

Swift generics subclass behaviour in Array

So I walk against this problem.
I have a BaseModel with some variables inside and a few normal "final" Models that inherit from the BaseModel.
If I have an array with class BaseModel with inside a few final models, and then loop trough those models and sent them to a function that uses generics. And check the class of the generics I get back they are from class BaseModel instead of the final class model that I need. How can I retrieve in a dynamic way the class of the final model. And of course I could cast them, but I would love to find a better solution.
See example in the playground I made:
import UIKit
class BaseModel {
var id: Int
init(id: Int) {
self.id = id
}
}
final class PersonModel: BaseModel {
var firstName: String
var surname: String
init(id: Int, firstName: String, surname:String) {
self.firstName = firstName
self.surname = surname
super.init(id: id)
}
}
func genericsTest<C: BaseModel>(with object: C) {
print("Class type: \(C.self)")
}
var person0 = PersonModel(id: 0, firstName: "John", surname: "Doe")
genericsTest(with: person0)
// This prints: "Class type: PersonModel"
var person1 = PersonModel(id: 1, firstName: "John1", surname: "Doe")
var person2 = PersonModel(id: 2, firstName: "John2", surname: "Doe")
var person3 = PersonModel(id: 3, firstName: "John3", surname: "Doe")
var personArray: [BaseModel] = [person0, person1, person2, person3]
for person in personArray {
print("Class type in for loop: \(person.self)")
// This prints: "Class type in for loop: __lldb_expr_195.PersonModel"
genericsTest(with: person)
// This prints: "Class type: BaseModel"
}
So in the for loop if I print the object.self I get the class I expect but in the function with generics do the same call I get the base class.
Edit 1:
So if it would be possible to make Generic C the type of the final model I would be able to create thing like:
func genericsTest<C: BaseModel>(with type: C.Type, and object: C) {
let test = KeyPath<C, Int>
}
Just as example
Have a look at this
Question
You define a array of type 'BaseModel' so in your for loop it basically is saying
for let person: BaseModel in personArray
Making person of type BaseModel
In the function:
func genericsTest<C: BaseModel>(with object: C) {
print("Class type: \(C.self)")
}
You are using the type, in contrary in this code:
print("Class type in for loop: \(model.self)")
You are using the object. If you change the C to object you will get the same result.
Do remember if you going to use this in you project to determine what type of object this is. You need to seriously go back to your drawing board. Because this is not OOP!

Auto add a class instance to an array in Swift

How can I auto add a new class instance to an array?
Example:
class Product {
var name: String?
}
var products = [Product]()
How can I add a new instance of a Product class to the products Array? How can I append to the array?
I tried some code but I don't know how to reference the class in own class.
I tried something like this:
class Product {
var name: String?
init() {
products.append(Produt)
}
var products = [Product]()
Thanks!
If you want your newly created object stored in products array then you need to declare it as static property so that it is shared by all instance otherwise it will just add first object for your every instance.
class Product {
var name: String?
static var products = [Product]()
init() {
Product.products.append(self)
}
init(name: String) {
self.name = name
Product.products.append(self)
}
}
Now use this products array using Product.products.
_ = Product(name: "One")
_ = Product(name: "two")
print(Product.products)
I dont't know why you need it, but you can use
class Product {
static var products: [Product] = []
var name: String?
init() {
products.append(self)
}
}
Have you tried products.append(self) ?

Resources