FetchRequest based on subset criteria - core-data

Consider the following object graph:
#objcMembers class Event: NSObject {
let name: String
let sections: [Section]
init(name: String, sections: [Section]) {
self.name = name
self.sections = sections
}
}
#objcMembers class Section: NSObject {
let name: String
let videos: [Video]
init(name: String, videos: [Video]) {
self.name = name
self.videos = videos
}
}
#objcMembers class Video: NSObject {
let name: String
let isFavorite: Bool
let isWatched: Bool
init(name: String, isFavorite: Bool, isWatched: Bool) {
self.name = name
self.isFavorite = isFavorite
self.isWatched = isWatched
}
}
I would like to filter the event sections which only have the videos marked as favorites
let events = [Event(name: "2021 Event",
sections: [
Section(name: "Monday",
videos: [Video(name: "VideoMonday1",
isFavorite: true,
isWatched: true),
Video(name: "VideoMonday2",
isFavorite: false,
isWatched: true)]),
Section(name: "Tuesday",
videos: [Video(name: "VideoTuesday1",
isFavorite: false,
isWatched: false),
Video(name: "VideoTuesday2",
isFavorite: true,
isWatched: true)])
])
]
//Expected result
let filtered = [Event(name: "2021 Event",
sections: [
Section(name: "Monday",
videos: [Video(name: "VideoMonday1",
isFavorite: true,
isWatched: true)]),
Section(name: "Tuesday",
videos: [Video(name: "VideoTuesday2",
isFavorite: true,
isWatched: true)])
])
]
Im using CoreData, and i came up with this predicate:
let favPredicate = NSPredicate(format: "SUBQUERY(sections, $sect, SUBQUERY($sect.videos, $vid, $vid.isFavorite == YES).#count > 0).#count > 0")
This however doesnt exclude the videos which are not favorites, from the sections.
It s a query which runs on the event entity, and "it works" because it filters the array, but not what im looking for.
I can achieve this as soon as i get the root array: however, i d like to accomplish this using coreData, by not loading not needed objects in memory. Is this possible or its not worth in terms of complexity?

Related

Create list of only non-empty/non-null dictionaries

I'm creating a model in Pydantic to get a JSON-like format from a dataframe.
What I have so far is this:
from datetime import datetime
from pydantic import BaseModel
from typing import Optional, List, Deque, Union
from collections.abc import Sequence
class startDate (BaseModel):
year: int
month: int
day: int
class endDate (BaseModel):
year: int
month: int
day: int
class origin(BaseModel):
id: str
class destinations(BaseModel):
id: Optional[str] = None
class transfers_list(BaseModel):
unloadingDuration: Optional[str] = None
destination: Optional[destinations] = None
class frequency(BaseModel):
id: str
class routeDetails (BaseModel):
arrivalTime: str
loadingStartTime: str
loadingDuration: str
releaseVehicleDuration: str
vehicleType: str
carrierId: str
returnRoute: bool
dock: Optional[str]
origin: origin
transfers: Optional[list[transfers_list]] = None
frequency: frequency
class main (BaseModel):
region: str
startDate: startDate
endDate: endDate
recurrenceDays: list[int]
routeDetails: routeDetails
class head (BaseModel):
recurrenceSchedule: main
m = main(region='ABC',
startDate={'year': 2023,
'month': 1,
'day': 1},
endDate={'year': 2023,
'month': 1,
'day': 1},
recurrenceDays=[5],
routeDetails = {'arrivalTime':'09:00:00',
'loadingStartTime':'09:00:00',
'loadingDuration':'09:00:00',
'releaseVehicleDuration':'09:00:00',
'vehicleType':"truck",
'carrierId':"carrier_name",
'returnRoute':True,
'dock': None,
'origin': origin(id="NYC"),
'transfers': [transfers_list(unloadingDuration='10s', destination=destinations(id='id_destination')),transfers_list(unloadingDuration=None, destination=destinations(id=None))],
'frequency': frequency(id='247')
}
)
final = (head(recurrenceSchedule = m))
final = final.json(exclude_unset=True,exclude_defaults=True)
print(final)
And the Output is this:
{
"recurrenceSchedule":{
"region":"ABC",
"startDate":{
"year":2023,
"month":1,
"day":1
},
"endDate":{
"year":2023,
"month":1,
"day":1
},
"recurrenceDays":[
5
],
"routeDetails":{
"arrivalTime":"09:00:00",
"loadingStartTime":"09:00:00",
"loadingDuration":"09:00:00",
"releaseVehicleDuration":"09:00:00",
"vehicleType":"truck",
"carrierId":"carrier_name",
"returnRoute":true,
"origin":{
"id":"NYC"
},
"transfers":[
{
"unloadingDuration":"10s",
"destination":{
"id":"id_destination"
}
},
{
"destination":{
}
}
],
"frequency":{
"id":"247"
}
}
}
}
This is almost exactly what I need, but in my Dataframe I have other columns for unloadingDuration and Destination that are inside "Transfers". However, when the value in the DF is empty/null/None, I don't want another dictionary inside the list. My desired output is:
"transfers":[
{
"unloadingDuration":"10s",
"destination":{
"id":"id_destination"
}
}
]
Instead of this:
"transfers":[
{
"unloadingDuration":"10s",
"destination":{
"id":"id_destination"
}
},
{
"destination":{
}
}
]
I have tried changing my NaN fields (unloadingDuration and destination) in the dataframe to None, but this doesn't work.
I tried changing some classes to Optional back and forth and this didn't seem to work either.
I also used exclude_unset=True and exclude_defaults=True that do work in some cases (dock is Optional, and when I set it to null it simply doesn't show up).
Try excluding none values:
final = final.json(exclude_unset=True, exclude_none=True)

"Type 'User' does not conform to protocol 'Equatable'/ 'Hashable'

I want to add a variable of type View to my struct: User and then later add individual views to my users (as shown in Manuelle). However I get the error "Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements" and "Type 'User' does not conform to protocol 'Equatable'/ Hashable".
struct User : Hashable {
let name: String
let age: Int
let profilePicture, status, icon: String
let view: View
}
struct MyUserView: View {
let users = [
User(name: "Manuelle", age: 23, profilePicture: "person", status: "inactive", icon: "message.fill", view: UserProfileView()),
User(name: "Michael", age: 39, profilePicture: "person", status: "active 12 minutes ago", icon: "square.on.square")
]
var body: some View {
NavigationView {
List {
ForEach(users, id: \.self) { user in
HStack {
Text(user.name)
Image(systemName: user.profilePicture)
}
}
}
}
}
}
Remove let view: View from the User struct, that's the main problem.
Also, you can't supply id: \.self to the ForEach view. id has to be a property that is a unique identifier of the struct it cannot be the struct itself because you'll get a crash when the array of structs changes. You have a few options to fix it:
ForEach(users, id: \.name) { user in
Or better:
struct User : Identifiable {
var id: String {
return name
}
Because then you can simply do:
ForEach(users) { user in
But normally we do this:
struct User : Identifiable {
let id = UUID()
Unless of course the userID comes from a server.

Cannot convert value of type 'FetchedResults<Topic>' to expected argument type 'Set<Topic>'

Calling currentTopics(subject: subject, topics: topics) throws an error: Cannot convert value of type 'FetchedResults<Topic>' to expected argument type 'Set<Topic>'.
This is the code:
func currentTopics(subject: Subject, topics: Set<Topic>) -> Set<Topic> {
var collected: Set<Topic> = []
for topic in topics {
if subject.topics!.contains(topic) {
collected.insert(topic)
}
}
return collected
}
And this is the declaration part:
struct TopicView: View {
#State var subject: Subject
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(sortDescriptors: [NSSortDescriptor(key: "title", ascending: true)])
private var topics: FetchedResults<Topic>
...
}
What should I do to fix this?
I assume the signature should be
func currentTopics(subject: Subject, topics: FetchedResults<Topic>) -> Set<Topic> {

Is it possible to convert string to type in Scala reflection?

I want to convert string to type in scala.Take two following cases as an example:
case class Product(id: String, title: String, description: String)
type aType = Product
client.getProduct[aType](id, "/products").map { x => println(s"Retrieved Product with id '$id': $x") } // Working
// Retrieved Product with id 'test_id': Some(Product(test_id,MyTitle,The text of my Product))
case class Store(id: String, title: String, Address: String)
type aType = Store
client.getStore[aType](id, "/stores").map { x => println(s"Retrieved Store with id '$id': $x") } // working
// Retrieved Store with id 'test_id': Some(Store(test_id, Store Name,The address of my Store))
I want to make this code general for any request, given case classes are already defined. for example
case class Product(id: String, title: String, description: String)
case class Store(id: String, title: String, Address: String)
case class API_Detail(Name: String, CaseClassName: String, Api_Url:String)
var API_List = List[API_DS]()
val request_type = "Product" // or "Store"
val id = "test_id"
val API_List_Item = API_List.filter(_.Name == request_type)
// Want to do like this...
type aType = API_List_Item.CaseClassName.toType /**/
val RequestURL = API_List_Item.Api_Url
/* Interested to know how to convert string to type. To my knowledge
some form of reflection will be implemented. */
client.getRespone[aType](id, RequestURL).map { x => println(s"Retrieved $request_type with id '$id': $x") } // Working
// Retrieved Product with id 'test_id': Some(Product(test_id,MyTitle,The text of my Product))
thanks for inviting me to this thread. Perhaps you can keep the solution simple enough by using pattern matching. The other solution using implicit class is also valid.
val requestUrl = "/products"
requestUrl match {
case "/products" => Products(...)
case "/store" => Store(...)
case _ => UnknownType
}
For additional examples on Pattern Matching, see my tutorial at allaboutscala.com
I'm extending my previous answer on Pattern Matching. There is no need to re-pattern match if we have a Polymorphic Function and I'm making use of Type Classes. I also provide detailed tutorials at allaboutscala.com on the building blocks for type classes: traits, implicits and functions in general.
You will need to expand getResponse(...) to build and populate the fields for your concrete types.
case class Product(id: String, title: String, description: String)
case class Store(id: String, title: String, address: String)
trait Client[T] {
def getResponse(s: String): Option[T]
}
object Client {
implicit val productClient: Client[Product] = new Client[Product] {
override def getResponse(s: String): Option[Product] = s match {
case "/product" => Some(Product("id", "title", "description"))
case _ => None
}
}
implicit val storeClient: Client[Store] = new Client[Store] {
override def getResponse(s: String): Option[Store] = s match {
case "/store" => Some(Store("id", "title", "address"))
case _ => None
}
}
def apply[T : Client](s: String): Option[T] =
implicitly[Client[T]].getResponse(s)
}
val product: Option[Product] = Client[Product]("/product")
val store: Option[Store] = Client[Store]("/store")

JTable not updating when its content changes

import groovy.beans.Bindable;
import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import javax.swing.JFrame
#Bindable def people = [[name:"Mary", age:18],
[name:"Tom", age:25]]
def swingBuilder = new SwingBuilder()
swingBuilder.edt { // edt method makes sure UI is build on Event Dispatch Thread.
lookAndFeel 'system' // Simple change in look and feel.
frame( title: 'Display a table',
size: [400,300],
show: true,
locationRelativeTo: null,
defaultCloseOperation: JFrame.EXIT_ON_CLOSE)
{
menuBar() {
menu(text: "File", mnemonic: 'F'){
menuItem(text: "Add",
actionPerformed: {
people << [name:"Harry", age:17]
println people
}
)}
}
panel(layout: new BorderLayout()) {
scrollPane(constraints: BorderLayout.CENTER) {
table() {
def listTeacher
tableModel(list: people) {
propertyColumn(header: 'Name', propertyName: 'name')
propertyColumn(header: 'Age', propertyName: 'age')
}
}
}
}
}
}
When click "Add" one entry is added to the list people but the JTable is not updated. How can I fix it?
You can make it an ObservableList, and then refresh the table model when the list changes in some way:
import groovy.beans.Bindable;
import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import javax.swing.JFrame
import java.beans.PropertyChangeListener
#Bindable ObservableList people = [ [name:"Mary", age:18],
[name:"Tom", age:25] ]
def swingBuilder = new SwingBuilder()
swingBuilder.edt { // edt method makes sure UI is build on Event Dispatch Thread.
lookAndFeel 'system' // Simple change in look and feel.
frame( title: 'Display a table',
size: [400,300],
show: true,
locationRelativeTo: null,
defaultCloseOperation: JFrame.HIDE_ON_CLOSE) {
menuBar() {
menu(text: "File", mnemonic: 'F'){
menuItem(text: "Add", actionPerformed: {
people << [name:"Harry", age:17]
println people
}
) }
}
panel(layout: new BorderLayout()) {
scrollPane(constraints: BorderLayout.CENTER) {
table {
def listTeacher
tableModel( id:'model', list: people) { m ->
propertyColumn(header: 'Name', propertyName: 'name')
propertyColumn(header: 'Age', propertyName: 'age')
}
}
}
people.addPropertyChangeListener( { e -> model.fireTableDataChanged() } as PropertyChangeListener )
}
}
}

Resources