I am wondering how can I define and initialize and array of structs inside a nested struct, for example:
type State struct {
id string `json:"id" bson:"id"`
Cities
}
type City struct {
id string `json:"id" bson:"id"`
}
type Cities struct {
cities []City
}
Now how can I Initialize such a structure and if someone has a different idea about how to create the structure itself.
Thanks
In your case the shorthand literal syntax would be:
state := State {
id: "CA",
Cities: Cities{
[]City {
{"SF"},
},
},
}
Or shorter if you don't want the key:value syntax for literals:
state := State {
"CA", Cities{
[]City {
{"SF"},
},
},
}
BTW if Cities doesn't contain anything other than the []City, just use a slice of City. This will lead to a somewhat shorter syntax, and remove an unnecessary (possibly) layer:
type State struct {
id string `json:"id" bson:"id"`
Cities []City
}
type City struct {
id string `json:"id" bson:"id"`
}
func main(){
state := State {
id: "CA",
Cities: []City{
{"SF"},
},
}
fmt.Println(state)
}
Full example with everything written out explicitly:
state := State{
id: "Independent Republic of Stackoverflow",
Cities: Cities{
cities: []City{
City{
id: "Postington O.P.",
},
},
},
}
Related
So i have a nested array of a model:
let models = [[ButtonModel]]
struct ButtonModel: Identifiable {
let id = UUID()
let value: String
let style: ColorStyle
init(_ value: String, _ style: ColorStyle) {
self.value = value
self.style = style
}
}
Then i want to add this as a grid so i have a VStack in which i loop x amount of HStacks with buttons in it.
But because of some reason i get this error:
Cannot convert value of type '[[ButtonModel]]' to expected argument type 'Binding'
Generic parameter 'C' could not be inferred
VStack {
ForEach(viewModel.buttons, id: \.self) { buttons in
HStack(spacing: GridPoints.x2) {
Spacer()
ForEach(buttons) { buttonValue in
if buttonValue == "/" {
imageButton(for: Asset.Image) { viewModel.addValue(buttonValue) }
} else {
Button(buttonValue, action: { viewModel.addValue(buttonValue) })
.buttonStyle(customFont: .h3)
.background(Color.backgroundColor)
.styleText(style: TextStyle.h3)
}
}
Spacer()
}
.padding(GridPoints.x1)
}
}
Anyone know what this error is?
Edit
It looks like you made a mistake when using buttonValue too.
You should use it like this
ForEach(buttons) { button in
if button.value == "/" {
imageButton(for: Asset.Image) { viewModel.addValue(button.value) }
}
...
}
ForEach requires an array whose every element is Identifiable (or telling which one is the id to use using id: \.something).
Your problem is that if you use an array of array, this means that every element of the outer array is another array which is NOT conforming to Identifiable.
If you use ForEach(arrayOfArray, id: \.self), on the other hand, your telling that the identifier will be each element of the outer array that must conform to Hashable. Array conform to Hashable if its element does. So try to change your struct to
struct ButtonModel: Identifiable, Hashable { ... }
Alternate solution
You could change your structure to
struct ButtonsGroup: Identifiable {
let id = UUID()
let buttons: [ButtonModel]
}
Then you will be using it like this:
let groups = [ButtonsGroup]()
ForEach(groups) { group in
ForEach(group.buttons) { button in
Text(button.value)
}
}
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) }
I have a JSON array which can contain either of two types defined by IPerson and ICompany.
[
{ "Name" : "Bob", "Age" : 50, "Address": "New Jersey"},
{ "Name" : "ABC Inc", "Founded" : 1970, "CEO": "Alice" }
]
This data is received from an endpoint. I want to map this data exactly in same way in my client application in Typescript. How should I define my model in this case.
I know we can define same interfaces in TypeScript but is it possible to have an array that holds either of two objects defined by IPerson and ICompany and know the type of each item while iterating the array?
You can have an Array<IPerson | ICompany>. For iterating, you can do something like this
function iterateMyArray(array: Array<IPerson | ICompany>) {
array.forEach(item => {
if ('Age' in item) {
// item is an person
console.log(item.Address);
} else {
// item is a company
}
})
}
I need to parse in Swift a data structure similar to this (based on a JSON):
[
{
"Name": "uniquename",
"Value": "John"
},
{
"Name": "locale",
"Value": "UK"
},
]
I stored this node in a struct like this
struct Rowset : Decodable {
var row: LoggedUserSession
init(loggedUser: [LoggedUserSession]){
self.row = loggedUser[0]
}
enum CodingKeys: String, CodingKey{
case row = "Row"
}
}
I prepared a similar struct to all the data I need to extract from the array but I don't know how to iterate on that and return the value when the name string match my case.
struct LoggedUserSession : Decodable {
var username: String;
var locale: String;
init(username: String, locale: String) {
// In JS I would embedd an iterator here and return the values
self.username = username
self.locale = locale
}
enum CodingKeys: String, CodingKey {
case username = "uniquename"
case locale = "locale"
}
}
If I understand what you are saying correctly, you want to parse an array of LoggedUserSession JSONs into a swift array of LoggedUserSessions. If that's the case, then you're almost there.
For completeness, I'm going to interpret the JSON you posted as follows so that it is valid:
{"loggedUserSessions":
[
{
"uniquename": "John",
"locale": "UK"
}
]
}
Your LoggedUserSession object is implemented correctly, so now all you need is the array parsing part. You can do that with the following struct:
struct SessionList: Decodable {
let sessions: [LoggedUserSession]
}
Calling this with JSONDecoder and your JSON data should serialize your list into an array that you can access via the SessionList's sessions property.
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].