How to retrieve array of elements from array of structure in golang? - arrays

I am new to golang, and got stuck at this. I have an array of structure:
Users []struct {
UserName string
Category string
Age string
}
I want to retrieve all the UserName from this array of structure. So, output would be of type:
UserList []string
I know the brute force method of using a loop to retrieve the elements manually and constructing an array from that. Is there any other way to do this?

Nope, loops are the way to go.
Here's a working example.
package main
import "fmt"
type User struct {
UserName string
Category string
Age int
}
type Users []User
func (u Users) NameList() []string {
var list []string
for _, user := range u {
list = append(list, user.UserName)
}
return list
}
func main() {
users := Users{
User{UserName: "Bryan", Category: "Human", Age: 33},
User{UserName: "Jane", Category: "Rocker", Age: 25},
User{UserName: "Nancy", Category: "Mother", Age: 40},
User{UserName: "Chris", Category: "Dude", Age: 19},
User{UserName: "Martha", Category: "Cook", Age: 52},
}
UserList := users.NameList()
fmt.Println(UserList)
}

No, go does not provide a lot of helper methods as python or ruby. So you have to iterate over the array of structures and populate your array.

No, not out of the box.
But, there is a Go package which has a lot of helper methods for this.
https://github.com/ahmetb/go-linq
If you import this you could use:
From(users).SelectT(func(u User) string { return u.UserName })
This package is based on C# .NET LINQ, which is perfect for this kind of operations.

Related

Group array by more than one property swift

Swift provides a method that converts array to dictionary on the basis of single property. Is it possible to group array to dictionary on the basis of more than one property. Something like following
For example we have array of objects containing name, age and gender
Person{
let name: String
let age: Int
let gender: String
}
And we have array containing persons
let array:[Person] = [Person(name: "Alex", age: 25, gender: "Male"), Person(name: "Sara", age: 25, gender: "Female")]
How can I group by multiple properties like name and age ?
Dictionary(grouping: array, by: { $0.name && $0.age })
You can group by anything that can become a key, in other words, by anything that is Hashable.
If you need to combine multiple properties, define a new type:
struct GroupingKey: Hashable {
let name: String
let age: Int
}
Dictionary(grouping: array, by: { GroupingKey(name: $0.name, age: $0.age) })

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) }

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" }

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!

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