Berechnungen in Core Data

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

  • Berechnungen in Core Data

    Hallo,

    in meiner Spritverbrauch APP möchte ich folgende Berechnungen durchführen und weiß nicht welches die beste Methode dazu ist,
    es geht mir um den Wert für "gefahrene Strecke" und "Verbrauch l/100km" .

    Es gibt da 2 Möglichkeiten:

    1. Ich füge in das Entity die Attribute "strecke" und "verbrauch" mit ein und speichere da die Werte.
    2. Ich berechne die Werte erst da wo ich sie benötige, also z.B. in der Tabelle der Tankvorgänge oder bei Statistikberechnungen.

    In beiden Fällen fehlt mir die Methode wie ich die Berechnung zu den Attributen ausführen könnte, ich denke ich muss
    in einer Schleife alle Objecte durchlaufen und immer die benötigten Werte des akt.Objectes für das nächste Object zur Berechnung merken.

    Für Möglichkeit 1 müsste ich dann jedes Object nach Eintrag des berechneten Wertes speichern, wo ich denke das könnte schlechte Performence
    mit sich bringen, zumal ich jai mmer das ganze Object speichere und jedes Object auch ein Foto beinhalten kann.

    Oder gibt es da eine andere Möglichkeit ?
    MfG. Bernhard
    (hb-mobilesoft.de)
  • Ich würde es immer berechnen wenn ich es brauche. In Deinem Fall kannst Du ganz einfach die Summe über ein Attribut biilden:

    Quellcode

    1. float theSum = [costs valueForKeyPath:@"@sum.value"];


    und dann durch die Anzahl teilen. Dann hast du den Verbrauch-

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Kay schrieb:

    Gefahrene Strecke wirst Du sicherlich sowieso abspeichern müssen oder?

    Nicht zwingend. Wenn die Tank-App Kilometerstand, Kraftstoffart, Liter und Preis speichert, dann kann sie an Hand der Kilometerstände aufeinander folgender Einträge die zurückgelegte Strecke berechnen.

    [Paulsche]
    Stichwort computed properties:
    Du kannst ja von NSManagedObject ableiten. Dort kannst Du Deinem Objekt Methoden wie '- (NSUInteger) distanceTo:' oder '- (double) consumptionComparedTo:' mitgeben: es erwartet als Parameter halt einen anderen Eintrag und liefert Dir die Werte gemäß Deiner Berechnung zurück.

    So kannst Du in einer Schleife beispielsweise abfragen:

    Quellcode

    1. [currentEntry distanceTo:previousEntry];


    Pro-Tip: die -consumptionComparedTo: kann zur Errechnung der Distanz auch auf die Distanz-Methode zugreifen. ;)

    Quellcode

    1. - (double) consumptionComparedTo:(instancetype)entry { // Wird nicht kompilieren. Wichtig ist nur, dass 'entry' eine Instanz sein muss, die auf einige passende Methoden reagieren kann.
    2. NSUInteger destination = [self distanceTo:entry];
    3. return [self consumption] / (destination*1.0);
    4. }


    Oder so in der Art halt.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Danke euch.

    Berechnungen über alle Daten wie Summe, denke ich ist nicht das Problem,
    es handelt sich eher um die Werte die sich von einem zum vorherigen Object
    berechnen, Beispiel:

    (Object 1)
    Tankdatum: 1.8.14
    KM-Stand: 2000km
    Liter: 55l

    (Object 2)
    Tankdatum: 10.8.14
    KM-Stand: 2800km
    Liter: 66l

    Strecke wäre hier 800km, Verbrauch 8,25l/100km

    Beim speichern von Strecke und Verbrauch mit den Einträgen müsste die Werte des vorherigen Eintrages vorher auslesen um berechnen zu können.
    Berechnen dieser Werte z.B. für Tabelle oder Statistik wäre nicht nötig.

    Normalerweise ist das speichern dieser Werte ja nicht notwendig, da sie ja jederzeit aus den vorhandenen Daten berechnet werden können,
    die Frage ist halt, was aufwändiger ist, bzw. sinnvoller, ich denke bei späterer Berechnung z.B. für Tabelle müssen dann alle Einträge
    in einer Schleife durchlaufen werden, da ich ja die werte aus jedem Object für das nächste Object holen muss.
    MfG. Bernhard
    (hb-mobilesoft.de)
  • Verstehe ich nicht. Du machst einen Predicate auf alle Objecte die du haben willst und bildest die Summe von Litern. Dann holst du dir noch einmal einzeln das erste Element deines Predicate und das letzet Object und ziehst die Kilometerstände vorneinander ab. Nun holst du noch die Anzahl der Object mit einem count und kannst alles errechnen was du willst.

    Ich sehe da keine Notwendigkeit einer Schleife oder irgendein Wissen welches OBject welchem folgt.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Ein Objekt könnte auch das/die Objekt(e) ermitteln, welche für die Berechnung von Differenzen etc. zu einem anderen Objekt erforderlich sind. Ein ManagedObject kann über den vorhandenen ManagedObjectContext die benötigten Objekte passend ermitteln.

    Alternativ könntest Du der Entity z.B. auch eine Relationship nextXXX und/oder previousXXX hinzufügen, welche auf das "vorherige" bzw. "nächste" Objekt der "Liste" zeigt. Dies führt beim nachträglichen Einfügen oder Entfernen von Objekten jedoch zu ein wenig mehr Aufwand in der Verkettung der neuen bzw. gelöschten Objekte.
  • Thallius schrieb:

    Ich sehe da keine Notwendigkeit einer Schleife oder irgendein Wissen welches OBject welchem folgt.

    Ich sehe da keine Notwendigkeit den Spritverbrauch der vergangenen 18 Monate zu errechnen.
    Da halte ich persönlich den Spritverbrauch vom letzten bis zum aktuellen Tanken für sinnvoller.

    Diese Assoziation bekommst Du ohne Änderungen am Modell bestenfalls über eine Schleife hin.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Thallius schrieb:

    Verstehe ich nicht. Du machst einen Predicate auf alle Objecte die du haben willst und bildest die Summe von Litern. Dann holst du dir noch einmal einzeln das erste Element deines Predicate und das letzet Object und ziehst die Kilometerstände vorneinander ab. Nun holst du noch die Anzahl der Object mit einem count und kannst alles errechnen was du willst.

    Ich sehe da keine Notwendigkeit einer Schleife oder irgendein Wissen welches OBject welchem folgt.

    Gruß

    Claus


    Hm, für die Berechnung der Strecke von der letzten Tanklung zur aktuellen Tankung benötige ich doch den KM-Stand der letzten Tankung.
    Ich möchte nicht die Strecke aller Tankungen sondern von der letzen zur aktuellen. Akt.KM-Stand minus letzter KM-Stand.
    MfG. Bernhard
    (hb-mobilesoft.de)
  • Marco Feltmann schrieb:

    Thallius schrieb:

    Ich sehe da keine Notwendigkeit einer Schleife oder irgendein Wissen welches OBject welchem folgt.

    Ich sehe da keine Notwendigkeit den Spritverbrauch der vergangenen 18 Monate zu errechnen.
    Da halte ich persönlich den Spritverbrauch vom letzten bis zum aktuellen Tanken für sinnvoller.

    Diese Assoziation bekommst Du ohne Änderungen am Modell bestenfalls über eine Schleife hin.


    Genau, das meine ich, currentEntry distanceTo:previousEntry hört sich da gut an,
    das werde ich mir mal reinziehen.

    Die Frage ist halt nun, bei der Eingabe die Werte zum vorherigen Object berechnen und mit speichern,
    oder bei Tabelle erstellen berechnen ?
    MfG. Bernhard
    (hb-mobilesoft.de)
  • Marco Feltmann schrieb:

    Thallius schrieb:

    Ich sehe da keine Notwendigkeit einer Schleife oder irgendein Wissen welches OBject welchem folgt.

    Ich sehe da keine Notwendigkeit den Spritverbrauch der vergangenen 18 Monate zu errechnen.
    Da halte ich persönlich den Spritverbrauch vom letzten bis zum aktuellen Tanken für sinnvoller.

    Diese Assoziation bekommst Du ohne Änderungen am Modell bestenfalls über eine Schleife hin.


    Kann er nicht einfach über ein predicate nur die MO's summieren die innerhalb eines Zeitraumes liegen?

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Thallius schrieb:

    Marco Feltmann schrieb:

    Thallius schrieb:

    Ich sehe da keine Notwendigkeit einer Schleife oder irgendein Wissen welches OBject welchem folgt.

    Ich sehe da keine Notwendigkeit den Spritverbrauch der vergangenen 18 Monate zu errechnen.
    Da halte ich persönlich den Spritverbrauch vom letzten bis zum aktuellen Tanken für sinnvoller.

    Diese Assoziation bekommst Du ohne Änderungen am Modell bestenfalls über eine Schleife hin.


    Kann er nicht einfach über ein predicate nur die MO's summieren die innerhalb eines Zeitraumes liegen?

    Gruß

    Claus


    Der Zeitraum ist ja nicht bekannt, ich brauche immer genau den vorherigen Eintrag zum aktuellen.
    MfG. Bernhard
    (hb-mobilesoft.de)
  • Ich glaube nicht, dass 'einfach' das richtige Wort ist.
    Er will ja 'einfach' die letzte Tankung haben.

    Fährt (und tankt) der Anwender täglich? Steht das Auto auch mal fünf Monate ungenutzt in der Garage?
    Wie definiert sich denn das 'Zeitraum' von 'innerhalb eines Zeitraumes'?

    Meiner Meinung nach ist 'letztes Mal' wesentlich genauer festzumachen als 'das späteste Ereignis innerhalb der letzten <Anzahl> <Einheit>'.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Thallius schrieb:

    Dan würde ich mit einer einfachen auto increment UniqueID arbeiten.

    Gruß

    Claus


    Die Daten sind nach Datum sortiert.
    Ich denke das einfachste wird sein, bei Tankeingabe auf den vorherigen Eintrag zugreifen und Werte auslesen,
    Strecke und Verbrauch mit dem Eintrag speichern, so benötige ich keine Schleife für Tabelle, da die Werte ja schon gespeichert sind
    und nicht berechnet werden müssen.
    MfG. Bernhard
    (hb-mobilesoft.de)
  • Wenn Du das Modell eh anpassen willst, solltest Du eventuell eher eine Referenz 'previousEntry' nutzen.
    Damit kannst Du die Computed Properties verwenden und es lässt sich leichter erweitern, wenn Du noch auf andere Werte aus dem vorherigen Eintrag zugreifen möchtest.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Marco Feltmann schrieb:

    Wenn Du das Modell eh anpassen willst, solltest Du eventuell eher eine Referenz 'previousEntry' nutzen.
    Damit kannst Du die Computed Properties verwenden und es lässt sich leichter erweitern, wenn Du noch auf andere Werte aus dem vorherigen Eintrag zugreifen möchtest.


    Danke,

    Computed Properties sagt mir noch nichts, da muss ich mal schauen.
    feched Properties ist da wohl gemeint.
    MfG. Bernhard
    (hb-mobilesoft.de)
  • [MCDan]
    Also mir ist der Beitrag schon aufgefallen. Da ich mit der ersten Zeile aber nix anfangen konnte, habe ich mich auf die mir bekannteren Aspekte gestürzt.

    MCDan schrieb:

    Ein Objekt könnte auch das/die Objekt(e) ermitteln, welche für die Berechnung von Differenzen etc. zu einem anderen Objekt erforderlich sind. Ein ManagedObject kann über den vorhandenen ManagedObjectContext die benötigten Objekte passend ermitteln.

    Wie kann es das denn tun, wenn alle Objekte unsortiert sind und es dringend das Objekt finden muss, dass vor ihm erstellt wurde?

    [Paulsche]
    Nein nein, Computed Properties sind viel älter als Fetched Properties. Computed Properties gab es ja schon weit vor Core Data. ;)
    Es ist einfach eine Methode, die beim Aufruf keine gespeicherte Property, sondern einen berechneten Werk zurück gibt.
    Das lässt sich am Einfachsten als Read Only Property beschreiben, die nie gesetzt wird, sondern sich aus dem Kontext ergibt.

    Mal ein bisschen Pseudo-Code als Beispiel:

    Quellcode

    1. @interface Dummy : NSObject {
    2. NSUInteger _duration;
    3. }
    4. - (NSUInteger)duration;
    5. // Absichtliche Objective-C 1.0 Notation
    6. @property NSUInteger start;
    7. @property NSUInteger end;
    8. @end
    9. @implementation Dummy
    10. // Selbst erstellte Stored Property
    11. - (NSUInteger) duration {
    12. return _duration;
    13. }
    14. // Selbst erstellte Computed Property
    15. - (NSUInteger) duration {
    16. return _end - _start;
    17. }
    18. @end
    Alles anzeigen


    Ich hoffe, der Unterschied ist erkennbar.
    Obwohl der Anwender des Objektes in beiden Fällen auf die Methode -duration zugreift, weiß er nicht, was er bekommt.
    Also er weiß nicht, ob das zurückgegebene Resultat jetzt gespeichert oder berechnet wurde. Das braucht er auch gar nicht zu wissen. ;)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Marco Feltmann schrieb:

    [MCDan]
    Also mir ist der Beitrag schon aufgefallen. Da ich mit der ersten Zeile aber nix anfangen konnte, habe ich mich auf die mir bekannteren Aspekte gestürzt.

    MCDan schrieb:

    Ein Objekt könnte auch das/die Objekt(e) ermitteln, welche für die Berechnung von Differenzen etc. zu einem anderen Objekt erforderlich sind. Ein ManagedObject kann über den vorhandenen ManagedObjectContext die benötigten Objekte passend ermitteln.

    Wie kann es das denn tun, wenn alle Objekte unsortiert sind und es dringend das Objekt finden muss, dass vor ihm erstellt wurde?

    [Paulsche]
    Nein nein, Computed Properties sind viel älter als Fetched Properties. Computed Properties gab es ja schon weit vor Core Data. ;)
    Es ist einfach eine Methode, die beim Aufruf keine gespeicherte Property, sondern einen berechneten Werk zurück gibt.
    Das lässt sich am Einfachsten als Read Only Property beschreiben, die nie gesetzt wird, sondern sich aus dem Kontext ergibt.

    Mal ein bisschen Pseudo-Code als Beispiel:

    Quellcode

    1. @interface Dummy : NSObject {
    2. NSUInteger _duration;
    3. }
    4. - (NSUInteger)duration;
    5. // Absichtliche Objective-C 1.0 Notation
    6. @property NSUInteger start;
    7. @property NSUInteger end;
    8. @end
    9. @implementation Dummy
    10. // Selbst erstellte Stored Property
    11. - (NSUInteger) duration {
    12. return _duration;
    13. }
    14. // Selbst erstellte Computed Property
    15. - (NSUInteger) duration {
    16. return _end - _start;
    17. }
    18. @end
    Alles anzeigen


    Ich hoffe, der Unterschied ist erkennbar.
    Obwohl der Anwender des Objektes in beiden Fällen auf die Methode -duration zugreift, weiß er nicht, was er bekommt.
    Also er weiß nicht, ob das zurückgegebene Resultat jetzt gespeichert oder berechnet wurde. Das braucht er auch gar nicht zu wissen. ;)


    ok, also eine Methode die mir den berechneten Wert als Ergebnis z.B. der Strecke zurückgibt.
    MfG. Bernhard
    (hb-mobilesoft.de)