I have two objects:
let obj1 = {
FirstName: "John",
LastName: "Doe",
age: 20,
color: "Purple"
}
let obj2 = {
FirstName: "John",
LastName: "Doe",
color: "Purple
}
As you can see, I got two almost similar 2 objects.
The only difference is that the second object doesn't have "age" property in it.
I want to compare between them and check if the second object is "contained" in the first one.
I tried
expect(obj1).toContain(obj2);
It doesn't work.
Is that even possible option?
If the objects are the same you can use Equatable, for example:
struct Person: Equatable {
var name: String?
var color: UIColor?
var LastName: String?
}
var person1 = Person()
person1.name = "roei"
person1.LastName = "b"
person1.color = .blue
var person2 = Person()
person2.name = "roei"
person2.LastName = "b"
person2.color = .blue
if person1 == person2 {
print("good")
}
it will print good
Related
I'm about to finish my App, similar to Tinder, but when I can't figure out how to match users based on their food likings, via their Sets of Food.
Is .filter() the way to go?
Video showing user selection of Food and CardView
CardStack will be the compilation of all CardView that will be presented to the user matched in its likings.
struct CardStack: View {
var people: [Person]
#State private var fullscreenMode: Bool = false
var body: some View {
ZStack {
ForEach(people) { person in
CardView(person: person, fullscreenMode: $fullscreenMode)
}
}
}
}
Meanwhile Person is the parameter taken on CardView, that the user will then match to.
struct Person: Hashable, Identifiable {
var id = UUID().uuidString
var foodLikings: Set<Food>
init(id: UUID) {
self.foodLikings = Set(arrayLiteral: Food(id: 3, name: "Empanadas", foodImage: ["empanadas"]), Food(id: 1, name: "Asado", foodImage: ["asado"]))
}
}
Here's what the Set<Food> consists of:
struct Food: Identifiable, Hashable {
var id: Int
let name: String
let foodImage: [String]
// Equatable
static func == (lhs: Food, rhs: Food) -> Bool {
lhs.id == rhs.id
}
}
All the available options for Food selection:
class FoodDataService {
static let comidas: [Comida] = [
Comida(
id: 0,
name: "Asado",
foodImage: ["asado"]
),
Food(
id: 1,
name: "Pizzas",
foodImage: ["pizzas"]
),
Food(
id: 2,
name: "Milanesas",
foodImage: ["milanesas"]
),
Food(
id: 3,
name: "Empanadas",
foodImage: ["empanadas"]
)
}
And finally what the User's struct is made of:
var person: Person
var user: User
struct User {
var foodLikings: Set<Food>
}
Found a much easier way to match users by simply using .contains().
if favoriteList.contains(personFavoriteList) {
// Show matched people
} else {
// Show other
}
Where personFavoriteList and favoriteList are strings returned as their likings mapped and sorted.
I am stuck with this guy [ : []]. As you can see, currently inside function I am using [0] to access value, but with this type of solution I can only access first element of array. How can I access all values? I tried with for in loop, but couldn't solve it...
Thanks in advance!
func tripServices(tripId: String) {
networkManager.getBookedTripsDetails(endpoint: "/v1/bookings/\(tripId)", tripId: tripId) { [unowned self] (safeTripsDetails) in
DispatchQueue.main.async {
self.bookedTripDetails = self.createScreenData(from: safeTripsDetails!, singleTrip: self.singleTrip!)
self.tableView.reloadData()
}
}
}
func createScreenData(from data: [String: [BookingService]], singleTrip: BookedTripsForView) -> [DetailsAboutServiceForView] {
return data.map{ ( data) -> DetailsAboutServiceForView in
return DetailsAboutServiceForView(id: singleTrip.id,
destination: data.value[0].destination,
tripStatus: data.value[0].status,
tripStartTime: data.value[0].startDate,
serviceName: data.value[0].serviceName,
serviceId: data.value[0].serviceId)
}
}
If you have a dictionary of arrays, and you want your output to be a single array containing all of the arrays combined into one array of a different type, there are various ways you could do that.
Rather than trying to work out your data types, I banged out an example using simple structs:
//Source struct
struct Person {
let name: String
let age: Int
}
//Output struct
struct Employee {
let name: String
let age: Int
let salary: Int?
}
let dictOfArrays = ["key1": [Person(name: "Bob", age: 36),
Person(name: "Felecia", age: 27),
Person(name: "Armin", age: 19)],
"key2": [Person(name: "Janet", age: 57),
Person(name: "John", age: 12),
Person(name: "Karen", age: 43)]
]
//Create an empty array for the output
var output = [Employee]()
//Loop through the dictionaries
dictOfArrays.forEach { (_, values) in
values.forEach { person in
//Only those who are >=18 can be employees
if person.age >= 18 {
output.append( Employee(name: person.name, age: person.age, salary: nil))
}
}
}
//Logs the resulting array of Employee structs.
output.forEach { print($0) }
Edit:
As pointed out by Alexander in his comment, you can do the above in one statement without creating an array var and appending to it using a combination of flatmap, filter, and map:
let output = dictOfArrays.flatMap { (_, values) in
values.filter { $0.age >= 18 }
.map { person in
Employee(name: person.name, age: person.age, salary: nil)
}
}
I need to change values in array of object
Array of selected sports which is received from API
Update API Response
arrSelectedID = [["slug": cricket,
"id": 1,
"banner_image": https://_1558964043.jpg,
"name": Cricket,
"icons": {
black = "https://sport_icon_cricket_black.png";
green = "https://sport_icon_cricket_green.png";
grey = "https://sport_icon_cricket_gray.png";
white = "https://sport_icon_cricket_white.png";
}],
["slug": soccer,
"banner_image": https://1558964051.jpg
"icons": {
black = "https://sport_icon_soccer_black.png";
green = "https://sport_icon_soccer_green.png";
grey = "https://sport_icon_soccer_gray.png";
white = "https://sport_icon_soccer_white.png";
},
"id": 2,
"name": Soccer]]
My Array
struct ObjSportsList:Codable {
var id:Int
var name:String
var slug:String
var selected:Bool?
var icons:ObjSportsIcon
}
struct ObjSportsIcon:Codable {
var green:String
var grey:String
var white:String
var black:String
}
var arrSports:[ObjSportsList] = [] // Array which is custom object
Below response is printed my custom object "ObjSportsList"
arrSports = (id: 1,
name: "Cricket",
slug: "cricket",
selected: nil,
),
(id: 2,
name: "Soccer",
slug: "soccer",
selected: nil,
),
(id: 3,
name: "Baseball",
slug: "baseball",
selected: nil,
),
I want to change "selected" values = true which is get id from API array in "data" Example : [1,3] only change 1st and 3rd selected values == true
I try to work with below code but array not updated
for (index, var sports) in self.arrSports.enumerated() {
for selectedSports in arrSelectedID {
if selectedSports["id"] as! Int == sports.id {
sports.selected = true
}
}
Please refer below code to replace the specific value in Array of object
let aryIDS = [1,3]
for (index, sport) in arrSports.enumerated(){
if aryIDS.contains(sport.id) {
arrSports[index].selected = true
}
}
print(arrSports) //Received updated array
I fix the issue with my own code, Please check this code
for (index, sports) in self.arrSports.enumerated() {
for selectedSports in arrSelectedID {
if selectedSports["id"] as! Int == sports.id {
self.arrSports[index].selected = true
}
}
}
How can I get my list data from a json object like this:
users: {
uid: {
name: "user1",
items: {
itemID1: {
name: "item1"
},
itemID2: {
name: "item2"
}
}
}
}
How can I get this list of Items and use it with an MVVM structure.
I tried to do the same thing that this article is doing with friends. But I am using firebase to load data.
https://medium.com/#stasost/ios-how-to-build-a-table-view-with-multiple-cell-types-2df91a206429
Thank you for your help!
It depends what you want if you want to display different cells for different users you ned String enum with cell registration and then have switch for them. I guess you don't want answer how to parse JSON.
For the article you need to fill the data model which looks like this
class Profile {
var fullName: String?
var pictureUrl: String?
var email: String?
var about: String?
var friends = [Friend]()
var profileAttributes = [Attribute]()
}
class Friend {
var name: String?
var pictureUrl: String?
}
class Attribute {
var key: String?
var value: String?
}
so you need data like this
users: {
uid: {
fullName: "user1",
pictureUrl: "svff",
email: "dfdf#gmail.com",
about: "Hello, world!",
friends: {
0: {
name: "Jon",
pictureUrl : "dfbdvsd"
},
1: {
name: "Tyrion",
pictureUrl : "dfbdvsd"
}
},
attributes: {
0: {
key: "key1",
value : "value1"
},
1: {
key: "key2",
value : "value2"
}
}
}
}
I've got the below struct and would like to sort the items within sessions by startTime field. I'm completely lost on how to do this.
I tried:
let sortedArray = sessionsData?.items.sorted{ ($0["startTime"] as! String) < ($1["startTime"] as! String) }
but that just gives me an error about no subscript members?
Any pointers would really be appreciated, thank you.
public struct sessions: Decodable {
let status: String?
let start: Int?
let count: Int?
let items: [sessionInfo]?
let itemsCount: Int?
let multipart: Bool?
let startTime: Int?
let endTime: Int?
}
public struct sessionInfo: Decodable {
let name: String?
let datalist: String?
let sessionType: Int?
let status: Int?
let backupType: Int?
let startTime: Int?
let endTime: Int?
let owner: String?
let numOfErrors: Int?
let numOfWarnings: Int?
let flags: Int?
}
I tried the below, but get an error:
var sortedArray = sessionsData?.items?.sorted(by: { (lhs, rhs) -> Bool in
return lhs.startTime < rhs.startTime
})
error:
Binary operator '<' cannot be applied to two 'Int?' operands
Try below code, it sorts the struct in asc order but it pushes nil timestamps to bottom.
if you want nil timestamps to be at top, make all nil checks in below code to return opposite of what i return in below code.
var sortedArray = sessionsData?.items?.sorted(by: { (lhs, rhs) -> Bool in
if let lhsTime = lhs.startTime, let rhsTime = rhs.startTime {
return lhs.startTime < rhs.startTime
}
if lhs.startTime == nil && rhs.startTime == nil {
// return true to stay at top
return false
}
if lhs.startTime == nil {
// return true to stay at top
return false
}
if rhs.startTime == nil {
// return false to stay at top
return true
}
})
You should access the fields directly and not through subscripts.
let sortedArray = sessionsData?.items.sorted(by: {$0.startTime < $1.startTime})
You could write this (tested in playground) :
var sortedArray = sessionsData?.items?.sorted(by: { (lhs, rhs) -> Bool in return (lhs.startTime ?? 0) < (rhs.startTime ?? 0) })
If one is optional, you do not crash, even though result of comparison is meaningless
You have default High Order Function for sorting the struct array in ascending and descending order
Example
let roster: [TeamMember] = [.init(id: 1, name: "Abishek", age: 19),
.init(id: 2, name: "Dinesh", age: 22),
.init(id: 3, name: "Praveen", age: 24),
.init(id: 4, name: "Sam", age: 25),
.init(id: 5, name: "David", age: 21)]
let descendingSorted = roster.sorted{$0.name > $1.name} // for descending order
let ascendingSorted = roster.sorted{$0.name < $1.name} // for ascending order
print(descendingSorted)
print(ascendingSorted)
Your Output
// for descending order
[TeamMember(id: 4, name: "Sam", age: 25.0),
TeamMember(id: 3, name: "Praveen", age: 24.0),
TeamMember(id: 2, name: "Dinesh", age: 22.0),
TeamMember(id: 5, name: "David", age: 21.0),
TeamMember(id: 1, name: "Abishek", age: 19.0)]
// for ascending order
[TeamMember(id: 1, name: "Abishek", age: 19.0),
TeamMember(id: 5, name: "David", age: 21.0),
TeamMember(id: 2, name: "Dinesh", age: 22.0),
TeamMember(id: 3, name: "Praveen", age: 24.0),
TeamMember(id: 4, name: "Sam", age: 25.0)]
And we have another one method for sorting is SortComparator. we sort the result based on ComparisonResult
let descendingSorted1 = roster.sorted { teamMember1, teamMember2 in
return teamMember1.name.compare(teamMember2.name) == .orderedDescending
} // for descending order
let ascendingSorted1 = roster.sorted{ teamMember1, teamMember2 in
return teamMember1.name.compare(teamMember2.name) == .orderedAscending
} // for ascending order
print(descendingSorted1)
print(ascendingSorted1)