I have two arrays and I would like to create a new array that compares the two and removes both instances of duplicates.
I have a custom object:
struct SubService: Identifiable, Hashable, Encodable {
var id: String = UUID().uuidString
var name: String
var charge: String
var price: Double
}
My two arrays:
let array1: [SubService] = [SubService(name: "Men's Haircut", charge: "service", price: 10), SubService(name: "Fade", charge: "service", price: 10)]
let array2: [SubService] = [SubService(name: "Fade", charge: "service", price: 10)]
Here is the result I'm looking for:
let result: [SubService] = [SubService(name: "Men's Haircut", charge: "service", price: 10)]
I have tried the following but it returns the same array as array1. I'm assuming because of the id?
let filteredArray = Array(Set(array1).subtracting(array2))
print statements:
ARRAY 1: [SubService(id: "F9EDBBC0-3786-4718-B6BE-C31F26D6E0F0", name: "Fade", charge: "service", price: 10.0), SubService(id: "D91939DD-C339-4A56-B09D-C19ABA56A48B", name: "Men\'s Haircut", charge: "service", price: 10.0)]
ARRAY 2: [SubService(id: "373CE5F9-ECB0-4572-BD27-8BC71F96163B", name: "Fade", charge: "service", price: 10.0)]
FILTERED ARRAY: [SubService(id: "D91939DD-C339-4A56-B09D-C19ABA56A48B", name: "Men\'s Haircut", charge: "service", price: 10.0), SubService(id: "F9EDBBC0-3786-4718-B6BE-C31F26D6E0F0", name: "Fade", charge: "service", price: 10.0)]
Any help is appreciated :)
SubService has to conform to protocol Equatable
struct SubService: Identifiable, Hashable, Encodable, Equatable {
var id: String = UUID().uuidString
var name: String
var charge: String
var price: Double
static func ==(lhs: SubService, rhs: SubService) -> Bool {
return lhs.name == rhs.name
}
}
let arrSet = Set(array2)
let filteredArray = array1.filter{ !arrSet.contains($0) }
Reuse your items instead of creating new ones for each array declaration.
let mens = SubService(name: "Men's Haircut", charge: "service", price: 10)
let womens = SubService(name: "Woman's Haircut", charge: "service", price: 10)
let array1 = [mens, womens]
let array2 = [womens]
When you redefine the second item of array1 in let array2 = ..., you create a new UUID that makes it different. You can actually see that in your printed values.
Related
This is a model of my makeshift database
var categories: [Category] = [
Category(name: "X",
sign: [Sign(code: "X-1", name: "***", description: "", picture: ""),
Sign(code: "X-2", name: "***", description: "", picture: "")]),
Category(name: "Y",
sign: [Sign(code: "Y-1", name: "Yyy", description: "", picture: ""),
Sign(code: "Y-2", name: "yyy", description: "", picture: "")]),
Category(name: "Z",
sign: [Sign(code: "Z-1", name: "Zzz", description: "", picture: ""),
Sign(code: "Z-2", name: "ZZZ", description: "", picture: "")])
]
I need to get one random element of any category (not one from each) from this base and print it as sign.code
I prepared the variable to store the value:
var RandomSign: Sign
And tried to do it with for loop:
func randomSign() {
for categorie in categories {
randomSign = categorie.sign.randomElement()
But, in the result, my loop generate me random element from each category, and finally save only random from the last one. I would like print for example "X-2" in my consol as random selected value.
Why not pick a random category and then a random sign from that random category?
func randomSign() {
randomSign = categories.randomElement()!.sign.randomElement()!
}
This code will crash if any of the arrays are empty. It would be safer if randomSign was optional then you can do:
func randomSign() {
randomSign = categories.randomElement()?.sign.randomElement()
}
Or you could fallback to a default Sign:
func randomSign() {
randomSign = categories.randomElement()?.sign.randomElement() ?? Sign(code: "empty", name: "***", description: "", picture: "")
}
I'm new in Swift, and I can't figure out how to filter these 2 arrays
var arrayOfFavoriteRoomsId = ["1", "2"]
var arrayOfRooms = [
VoiceRoom(id: "1", title: "Room1", description:"Test room1"),
VoiceRoom(id: "2", title: "Room2", description:"Test room2"),
VoiceRoom(id: "3", title: "Room3", description:"Test room3")
]
The final array should look like this
var filteredArray = [
VoiceRoom(id: "1", title: "Room1", description:"Test room1"),
VoiceRoom(id: "2", title: "Room2", description:"Test room2")
]
This is what my model looks like
struct VoiceRoom: Identifiable, Decodable {
var id: String
var title: String
var description: String
}
arrayOfRooms.filter { room in
arrayOfFavoriteRoomsId.contains(room.id)
}
If you want to sort them as well:
arrayOfRooms.filter { room in
arrayOfFavoriteRoomsId.contains(room.id)
}.sorted(by: { $0.id < $1.id })
I'm trying to decode Yelp's JSON. Within the file there's a nested array of categories. Some businesses have 1, others may have 3.
Here's an example
{
"businesses": [
{
"id": "4jW-ZDeCPIl9aXvTWcATlA",
"alias": "the-delaney-hotel-orlando",
"name": "The Delaney Hotel",
"image_url": "https://s3-media2.fl.yelpcdn.com/bphoto/fikUF4yC5J63f3EOCZ8uOw/o.jpg",
"is_closed": false,
"url": "https://www.yelp.com/biz/the-delaney-hotel-orlando?adjust_creative=s-hyKAjsx6P4UW-uqMn7aQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=s-hyKAjsx6P4UW-uqMn7aQ",
"review_count": 13,
"categories": [
{
"alias": "hotels",
"title": "Hotels"
},
{
"alias": "venues",
"title": "Venues & Event Spaces"
}
],
"rating": 5.0,
...etc
}
]
My data model is set up this way
struct BusinessesResponse: Codable {
enum CodingKeys: String, CodingKey {
case restaurants = "businesses"
}
let restaurants: [RestaurantResponse]
}
struct RestaurantResponse: Codable, Identifiable, Equatable {
let id: String
var name: String
var image_url: String
var is_closed: Bool
var review_count: Int
var rating: Double
var distance: Double
var price: String?
var display_phone: String?
var categories: [HotelCategory]
var coordinates: HotelCoordinates
var location: HotelLocation
var transactions: [String]
}
struct HotelCategory: Hashable, Codable {
var title: String
}
struct HotelCoordinates: Hashable, Codable {
var latitude: Double
var longitude: Double
}
struct HotelLocation: Hashable, Codable {
var address1: String
var city: String
var state: String
var zip_code: String
}
I'm able to display everything other than the first pair in the categories array. My guess is that I would need to set a ForEach statement to display all available information from that array, but I'm not sure how to set that up correctly.
Here's what I have currently in abbreviated form
var category: [HotelCategory]
var body: some View {
HStack {
Text("\(category[0].title)")
}
}
Obviously that would only return the first child of that nested array. How would I dynamically account for that nested array having multiple children and then displaying them?
You can use ForEach this way:
ForEach(category, id: \.self) { category in
HStack {
Text("\(category.title)")
}
}
Note: if you're not sure that categories are unique, it might be better to conform HotelCategory to Identifiable and use id: \.id.
I'd also recommend following the convention and naming arrays with plural names, i.e.:
var categories: [HotelCategory] // instead of `category`
I have 2 arrays of maps where one of them has product ids and quantities; and the other one has product ids, product names and price:
List<Map<String, dynamic>> arr1 = [
{ id: "1", name:"First Item", price: 10 },
{ id: "2", name: "Second Item", price: 12 }
];
List<Map<String, dynamic>> arr2 = [
{ id: "1", quantity: 1 },
{ id: "2", quantity: 3 },
{ id: "3", quantity: 2 }
];
Now I need to get total price of products by combining two arrays by obtaining sum of price * quantites.
I need an array similar to this:
List<Map<String, dynamic>> arr3 =[
{ id: "1", name:"First Item", price: 10, quantity: 1 },
{ id: "2", name: "Second Item", price: 12, quantity: 3 }
];
How can I merge them into one array based on their ids?
You can merge the array by mapping the first array to the second one.
final arr3 = arr1.map((product) {
final quantity = arr2
.where((quantities) => quantities["id"] == product["id"])
.map((quantities) => quantities["quantity"] as int)
.first;
return product..["quantity"] = quantity;
});
Full example: https://dartpad.dev/67148d132cb930bc6f1cee6a8a4fcff1
New to swiftUI, and I need to show the images and their names randomly by action of a button. How should I call the pictures' array to show a random picture each time user tap on the button in the contentView file ?
this is the array of pictures that I want to show them randomly in contentView(pictures placed in Assets folder):
struct aPicture: Identifiable {
var id: Int
var name: String
var imageName: String
}
let pictures = [
aPicture(id: 0, name: "1", imageName: "1"),
aPicture(id: 1, name: "2", imageName: "2"),
aPicture(id: 2, name: "3", imageName: "3"),
aPicture(id: 3, name: "4", imageName: "4"),
aPicture(id: 4, name: "5", imageName: "5"),
aPicture(id: 5, name: "6", imageName: "6"),
]
you can try this:
struct ContentView: View {
struct aPicture: Identifiable {
var id: Int
var name: String
var imageName: String
}
#State var random : Int = 0
let pictures = [
aPicture(id: 0, name: "1", imageName: "1"),
aPicture(id: 1, name: "2", imageName: "2"),
aPicture(id: 2, name: "3", imageName: "3"),
aPicture(id: 3, name: "4", imageName: "4"),
aPicture(id: 4, name: "5", imageName: "5"),
aPicture(id: 5, name: "6", imageName: "6"),
]
var body: some View {
VStack {
HStack {
Spacer()
Text(pictures[self.random].name)
.background(Color.white)
Spacer()
Button("Next image") {
self.random = Int.random(in: 0..<self.pictures.count)
}
Spacer()
}
Image(pictures[self.random].imageName)
.resizable()
.scaledToFit()
}
}
}
I suggest you different approach.
1) you can generate random element directly
let picture = pictures.randomElement() ?? default_if_empty_collection
2) user would like to see different picture after tap, which could not be true. Less pictures in your "store", more likely randomly you generate the same picture (which could looks like "nothing happens on tap")
next snippet shows how to solve this. On every tap the user see different picture, even though there are just tree pictures in our collection.
import SwiftUI
struct ContentView: View {
#State var img = Image(systemName: "questionmark.square.fill")
let imgs = [Image(systemName: "trash"),
Image(systemName: "trash.fill"),
Image(systemName: "trash.slash"),
]
var body: some View {
img
.resizable()
.scaledToFit()
.frame(maxWidth: .infinity)
.onTapGesture {
var tmp: Image
repeat {
tmp = self.imgs.randomElement() ?? self.img
} while tmp == self.img
self.img = tmp
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}