heinetz: JavaScript Objecte ... mergen/summieren

Hallo Forum,

ich würde meinen JS-Code gerne etwas optimieren ... Konkret:

const a = {
 contribute: 10,
 affected: 10
}

const b = {
 contribute: 10,
 affected: 10
} 

const c = {
 contribute: a.contribute + b.contribute,
 affected: a.contribute + b.contribute
} 

Die beiden Objekte haben immer die selbe Datenstruktur. Kann ich Objekt c 'eleganter' zusammenbauen. Ich summiere ja gleichnamige properties. Lässt sich das ausdrücken ohne die properties zu kennen?

danke für Tipps und

beste Grüße, heinetz

  1. Hallo,

    du könntest dir eigene Methoden schreiben, um mit deinen Objekten zu rechnen, z.B.:

    c = my_sum(a,b);
    

    wenn du mehrere Eigenschaften deiner Objekte verrechnen musst, wäre eine for-in-Schleife evtl. eine Lösung.

    Gruß
    Jürgen

    1. du könntest dir eigene Methoden schreiben, um mit deinen Objekten zu rechnen, z.B.:

      c = my_sum(a,b);
      

      wenn du mehrere Eigenschaften deiner Objekte verrechnen musst, wäre eine for-in-Schleife evtl. eine Lösung.

      Wenn man die my_sum-Funktion schon hat, kann man daraus mit Array.prototype.reduce auch einfach eine Funktion für Listen machen:

      function my_sum_list(list) {
        return list.reduce(my_sum, {
          contribute: 0,
          affected: 0
        })
      }
      

      Der zweite Paramter gibt einfach den Startwert an, bzw. den Rückgabewert für leere Listen.

      1. Hallo 1unitedpower,

        ihr überseht alle, dass heinetz gerade nach dem Kern von my_sum fragt: Wie komme ich an die Liste der Propertynamen heran.

        Rolf

        --
        sumpsi - posui - clusi
        1. Hallo,

          ihr überseht alle, dass heinetz gerade nach dem Kern von my_sum fragt: Wie komme ich an die Liste der Propertynamen heran.

          durchaus nicht: Den Hinweis auf das for-in-Konstrukt, das genau diese Aufgabe löst, hat JürgenB gleich im ersten Antwortposting gegeben.

          Ciao,
           Martin

          --
          Ich stamme aus Ironien, einem Land am sarkastischen Ozean.
          1. oops ;)

            Rolf

            --
            sumpsi - posui - obstruxi
  2. Hallo,

    affected: a.contribute + b.contribute

    Ich summiere ja gleichnamige properties.

    Soso, tust du das?

    Gruß
    Kalk

  3. Hallo heinetz,

    Lässt sich das ausdrücken ohne die properties zu kennen?

    1. Object.getOwnPropertyNames(obj) - liefert Dir ein Array mit den Namen der Properties, die ein Objekt hat.
    2. for...in Schleife - durchläuft die Namen der Properties eines Objekts

    Unterschied zwischen for...in und getOwnProperties ist, dass for...in auch die Properties der Prototypkette mit auflistet, also die Properties, die ein Objekt von seinen Prototypen erbt. Das ist egal, wenn Du keinen Prototypen hast, wie in deinem Beispiel.

    Du musst Dir dann die Frage beantworten, wie Du mit Properties umgehen willst, die nur in einem der beiden Objekte vorkommen. Willst Du die ignorieren? Willst Du fehlende Properties mit einem Defaultwert ersetzen (z.B. 0)?

    Und dann musst Du überlegen, wie Du deine Objektoperatoren designen willst. Denkbar wäre, dass Du Methoden wie add hinzufügst. Dann könnte man

    let c = a.add(b);
    

    schreiben. Operatorüberladung wie in C++, Java oder C# ist nicht möglich, d.h. eine Schreibweise wie let c = a + b;, bei der ein Addierhelper von Dir aufgerufen wird, ist nicht möglich. Eine add Methode sollte sich dann aber im Prototypen wiederfinden, sonst stört sie bei der Summierung.

    Einfacher ist wohl eine generelle Helperfunktion, die zwei Objekte oder ein Array von Objekten verarbeitet, so wie Jürgen vorschlug.

    Bevor Du addierst, musst Du die Liste der zu addierenden Properties bestimmen. Wenn die Objekte alle gleich strukturiert sind, ist das einfach. Aber wenn sie heterogen sind, brauchst Du eine Strategie. Wenn Du a:={foo:3, bar:4} und b:={foo:9, zap: 1}; addierst, welche Properties soll das Ergebnis haben? Nur foo? foo und bar? foo und zap? Oder foo, bar und zap?

    Am einfachsten machst Du es Dir, wenn das Ergebnis die gleichen Properties hat wie eins der addierten Objekte. Gerade bei einer Massenaddition musst Du dann lediglich die Properties des ersten Objekts bestimmen und die passenden Properties der übrigen Objekte draufaddieren. Sind die Objekte homogen, ist das ohnehin die beste Lösung.

    Und wie greifst Du auf ein Property zu, wenn Du seinen Namen nicht kennst? Dafür gibt's den [] Operator. Den kann man nicht nur bei Arrays verwenden, sondern auch, um auf Objekteigenschaften zuzugreifen.

    function sumObjects(a, b) {
       // todo: Prüfen ob a und b ungleich null sind.
    
       let propertiesToAdd = Object.getOwnPropertyNames(a);
    
       let summe = { };
       for (let name of propertiesToAdd) {
          summe[name] = a[name] + b[name];
       }
       return summe;
    }
    
    function array_sumObjects(arr) {
       // Todo: Prüfen ob arr ein Array ist
    
       let propertiesToAdd = Object.getOwnPropertyNames(arr[0]);
    
       let summe = { };
       for (let name of propertiesToAdd) {
          summe[name] = 0;
          for (let summand of arr)
             if (summand.hasOwnProperty(name))
                summe[name] += summand[name];
       }
       return summe;
    }
    

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo Forum,

      alles klar. Danke für die Ideen. Ich dache, es ginge auch anders als mit einer selbstgebauten Lösung. Aber gut, ich hab's mit Object.getOwnPropertyNames() gelöst. Das kannte ich nicht.

      schönen Abend und

      Gruss, heinetz