Liste filtern

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Liste filtern

    Hallo zusammen,

    ich würde gern eine Liste aller Elemente aus meinem Datenmodell erstellen, jedoch in Abhängigkeit, ob ein einem anderen Datenmodell ein Feld mit einem bestimmten Wert gefüllt ist.

    Hier mein Datenmodell:

    Quellcode

    1. struct MonthModel: Hashable {
    2. var description: String
    3. var name: String
    4. var order: String
    5. var record: CKRecord
    6. var uuid: String = UUID().uuidString
    7. init(description: String, name: String, order: String, record: CKRecord, uuid: String) {
    8. self.description = description
    9. self.name = name
    10. self.order = order
    11. self.record = record
    12. self.uuid = uuid
    13. } // end init
    14. } // end struct
    15. struct TrainingModel: Hashable {
    16. var description: String
    17. var monthId: String
    18. var name: String
    19. var practiceId: String
    20. var record: CKRecord
    21. var uuid: String = UUID().uuidString
    22. init(description: String, monthId: String, name: String, practiceId: String, record: CKRecord, uuid: String) {
    23. self.description = description
    24. self.monthId = monthId
    25. self.name = name
    26. self.practiceId = practiceId
    27. self.record = record
    28. self.uuid = uuid
    29. } // end init
    30. } // end struct
    Alles anzeigen


    Nun erstelle ich mir eine Liste der Element:

    Quellcode

    1. struct TestView: View {
    2. @EnvironmentObject var globalSettings: GlobalSettings
    3. @StateObject private var vmCKDb = CloudKitDBViewModel()
    4. var body: some View {
    5. VStack {
    6. List {
    7. ForEach (vmCKDb.months, id: \.self) { month in
    8. Text("\(month.uuid)")
    9. } // end foreach
    10. } // end list
    11. } //end vstack
    12. } // end var body
    13. } // end struct
    Alles anzeigen
    Soweit, so gut .....
    Jetzt kommt mein Problem: ich würde jedoch gern aber nur die Elemente anzeigen lassen, wenn im Datenmodell "Trainings" im Feld "monthId" auch die "month.uuid" des Datenmodells "Month" enthalten ist. Also wenn in irgendeinem Element von "Trainings" das Feld "monthId" den Wert von "month.uuid" enthält. Mein Versuch, welcher leider scheitert, sieht so aus:

    Quellcode

    1. ForEach (vmCKDb.months, id: \.self) { month in
    2. if vmCKDb.trainings.filter({$0.monthId == "\(month.uuid)"})
    3. {
    4. Text("\(month.uuid)")
    5. } // end if
    6. } // end foreach
    Es kommt der Fehler: Cannot convert value of type '[TrainingModel]' to expected condition type 'Bool'

    Ich hänge gerade in der Luft ........


    Die Zeile 2 soll alle Element im Datenmodell "Trainings" durchsuchen und prüfen, ob "month.uuid" in "monthId" enthalten ist. Sobald dieses in irgendeinem Element enthalten, dann soll es der Liste erscheinen.

    Vielleicht kann mir jemand einen Denkanstoß geben ...


    Vielen Dank vorab :rolleyes:
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • Das 'if / else' erwartet als Bedingung einen Bool-Parameter, du gibts aber das Result einer Filter-Operation zurück [TrainingModel]. Damit kann die 'if / else'-Verzweigung nichts anfangen. Du könntest eventuell fragen, ob das Result deiner Filter-Operation leer ist, so hast du einen Bool, den du dann als Parameter bei 'if / else' verwenden kannst.
  • Hallo Meister,

    immer wieder sind es dir kleinen Dinge .......

    Ich habe die Änderung im Code eingebracht:

    Quellcode

    1. ForEach (vmCKDb.months, id: \.self) { month in
    2. if !vmCKDb.trainings.filter({$0.monthId == "\(month.uuid)"}).isEmpty
    3. {
    4. Text("\(month.uuid)")
    5. } // end if
    6. } // end foreach
    In der Zeile 2 die "isEmpty" Property hinzugefügt (vorher für meine Lösung noch mit dem Ausrufezeichen negiert) und schon läuft alles wie gewünscht.

    Wieder nur eine kleine Änderungen, aber mit großer Wirkung.

    Herzlichen Dank für den Hinweis :thumbsup: :thumbsup: :thumbsup:
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • Jetzt möchte ich noch einen oben drauf legen ......

    Ich habe ein weiteres Datenmodell:

    Quellcode

    1. struct PracticeModel: Hashable {
    2. var age: String
    3. var category: String
    4. var description: String
    5. var level: String
    6. var name: String
    7. var record: CKRecord
    8. var uuid: String = UUID().uuidString
    9. init(age: String, category: String, description: String, level: String, name: String, record: CKRecord, uuid: String) {
    10. self.age = age
    11. self.category = category
    12. self.description = description
    13. self.level = level
    14. self.name = name
    15. self.record = record
    16. self.uuid = uuid
    17. } // end init
    18. } // end struct
    Alles anzeigen
    In meiner vorherigen ForEach Schleife durchlaufe ich alle Elemente in "Months" und suche mir aus "Trainings" alle Elemente, welche einen Eintrag in "month.uuid" haben.
    Erschwerend möchte ich in der Abfrage nun noch zusätzlich folgendes erreichen: in der if Abfrage möchte ich nicht nur prüfen, ob in "Trainings" die "monthId" dem Monat entspricht, sondern zusätzlich schauen, ob in "Practices" in "category" ein bestimmter String enthalten ist.

    Ich weiß nicht, bzw. habe es nicht geschafft, in vmCKDb.trainings.filter{} einen weiteren Filter hinzuzufügen.
    Ich weiß nicht, wie ich die Verknüpfung herstellen kann :(

    Ups, ich habe mich gerade selbst erschrocken, was ich da so geschrieben habe. Ich hoffe, man versteht mich ?(
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • Hi Michael,

    ich brauche jedoch in dem zweiten Filter das $0 des ersten Filters ......


    So etwas wie: vmCKDb.trainings.filter({$0.monthId == "\(month.uuid)" && vmCKDb.practices.filter{xxxxxxxx}}

    Dieses xxxxx muss dann etwas so etwas sein: $0.uuid == "\($0-von-trainingsfiter.practiceId)" && $0.category == "gesuchterString"

    Ich weiß nicht wie man Filter ineinander verschachtelt und wie man dann mit den $0 des vorherigen Filters umgeht oder verwendet. Ich hatte schon $0 und $1 etc. herumgespielt, bin jedoch nicht zum Erfolg gekommen.
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • Versuch mal openAi - ChatGPT für solche Fragen.
    Gerade für solche Fragen hilft es mir persönlich ganz gut, wenn ich mal solche Sachen vergessen habe.

    Habe nur mit einer Hirnhälfte deinen Betirag gelesen, aber evtl. hilft dir das ja:-)
  • Alles schön und gut, aber ich bekomme nur die Hilfe in chatgpt in folgender Art und Weise: array.filter{xxxx}.filter{yyyyy}


    Das hilft mir nicht weiter, da ich ja die einzelnen Elemente des einen Filters in den nächsten Filter mit verwenden muss .....


    Ich bleibe bei meiner Frage:

    So etwas wie: vmCKDb.trainings.filter({$0.monthId == "\(month.uuid)" && vmCKDb.practices.filter{xxxxxxxx}}


    Dieses xxxxx muss dann etwas so etwas sein: $0.uuid == "\($0-von-trainingsfiter.practiceId)" && $0.category == "gesuchterString"


    Ich weiß nicht wie man Filter ineinander verschachtelt und wie man dann mit den $0 des vorherigen Filters umgeht oder verwendet. Ich hatte schon $0 und $1 etc. herumgespielt, bin jedoch nicht zum Erfolg gekommen.


    Vielleicht kann mir nochmal jemand weiterhelfen :saint: :saint: :saint:
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von freelancer ()

  • Also, wenn ich das richtig verstanden habe, dann müsste das in etwa so gehen:

    Quellcode

    1. vmCKDb.trainings.filter({ $0.monthId == "\(month.uuid)" }).filter({ practiceForUUID($0.practiceId).category == "gesuchter String" })
    So eine practiceForUUID() Funktion müsstest du natürlich haben/programmieren.
  • Michael schrieb:

    Also, wenn ich das richtig verstanden habe, dann müsste das in etwa so gehen:

    Quellcode

    1. vmCKDb.trainings.filter({ $0.monthId == "\(month.uuid)" }).filter({ practiceForUUID($0.practiceId).category == "gesuchter String" })
    So eine practiceForUUID() Funktion müsstest du natürlich haben/programmieren.
    Habe ich auch so verstanden und so ähnlich sah auch die Antwort (meiner) ChatGpt Anfrage aus.
    Daher vermute ich, dass ich die Frage nicht richtig verstanden habe :D
  • Mein kleines Testscript liefert leider keine Ergebnisse zurück:

    Quellcode

    1. import SwiftUI
    2. struct TestView: View {
    3. @EnvironmentObject var globalSettings: GlobalSettings
    4. @StateObject private var vmCKDb = CloudKitDBViewModel()
    5. var body: some View {
    6. VStack {
    7. Text("globalsettings: " + String(globalSettings.hidePreviousMonths))
    8. List {
    9. ForEach (vmCKDb.months, id: \.self) { month in
    10. if (
    11. vmCKDb.trainings.contains{$0.monthId == "\(month.uuid)" && practiceToTrainingTest(practiceId: $0.practiceId)}
    12. ) {
    13. Text("\(month.name)")
    14. } // end if
    15. } // end foreach
    16. } // end list
    17. } //end vstack
    18. } // end var body
    19. } // end struct
    20. func practiceToTrainingTest(practiceId: String) -> Bool{
    21. @EnvironmentObject var globalSettings: GlobalSettings
    22. @StateObject var vmCKDb = CloudKitDBViewModel()
    23. var result: Bool = false
    24. print("fnction practiceToTraining")
    25. if (vmCKDb.practices.contains{$0.uuid == "\(practiceId)" && $0.age == globalSettings.selectedDiscipline}) {
    26. result = true
    27. } // end if
    28. return result
    29. } // end func
    Alles anzeigen

    In der Zeile 31 bekomme ich die Fehlermeldung: Accessing StateObject's object without being installed on a View. This will create a new instance each time.


    Michael hatte in seiner Codezeile:

    Quellcode

    1. vmCKDb.trainings.filter({ $0.monthId == "\(month.uuid)" }).filter({ practiceForUUID($0.practiceId).category == "gesuchter String" })
    ja einen filter in einen filter gelegt. Da wusste ich nicht, was ich in der Funktion machen sollte. Ich habe nun versucht eine Funktion zu schreiben, die einen positiven Wert zurückliefert. Leider ein Fehlversuch .....



    Wenn ich Zeile 31 einfach durch einen Ausdruck ersetze, welcher true ist, dann bekomme ich Ergebnisse geliefert.
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • So, und wieder ist ein Tag vergangen, aber ein erfolgreicher ....

    Meine Lösung sieht nun so aus:

    Quellcode

    1. struct TestView: View {
    2. @EnvironmentObject var globalSettings: GlobalSettings
    3. @StateObject private var vmCKDb = CloudKitDBViewModel()
    4. var body: some View {
    5. VStack {
    6. Text("globalsettings: " + String(globalSettings.hidePreviousMonths))
    7. List {
    8. ForEach (vmCKDb.months, id: \.self) { month in
    9. if (
    10. vmCKDb.trainings.contains{$0.monthId == "\(month.uuid)" && practiceToTrainingTest(practiceId: $0.practiceId)}
    11. ) {
    12. Text("\(month.name)")
    13. } // end if
    14. } // end foreach
    15. } // end list
    16. } //end vstack
    17. } // end var body
    18. private func practiceToTrainingTest(practiceId: String) -> Bool{
    19. var result: Bool = false
    20. print("function practiceToTraining")
    21. if (vmCKDb.practices.contains{$0.uuid == "\(practiceId)" && $0.age == globalSettings.selectedDiscipline}) {
    22. result = true
    23. }
    24. print("result: \(result)")
    25. return result
    26. } // end func
    27. } // end struct
    Alles anzeigen
    Ich habe vor allem die Fehlermeldung tausende Male gelesen; nun habe ich die Funktion innerhalb des struct der View :thumbsup: :thumbsup: :thumbsup: :thumbsup: :thumbsup:

    Ich bin Euch für die Hinweise und Denkanstösse wieder einmal sehr dankbar !!!!
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil: