Rolf B: javascript map() - auf bestimmte Elemente von value zugreifen

Beitrag lesen

problematische Seite

Hallo ebody,

Ich weiß halt nicht genau, was value alles enthält

Anhand deines Beispiels: Doch. Du weißt genau, dass das ein Objekt mit drei Eigenschaften ist: content, row und col.

Die filter-Methode kopiert diejenigen Einträge eines Arrays, für die die Callbackfunktion true liefert. Bei Dir ist der Callback (wenn ich Dedlfix' Anregung mit dem sprechenderen Namen aufgreife) dieser:

movie => movie.row === 1

D.h. das Ergebnis des filter-Aufrufs ist ein Array mit den Filmen Batman Begins und Blu Ray. Blauer Rochen? Nie gehört, ist der gut?

Achso, das sind ja gar nicht alles Filme. Es sind Spreadsheet-Zellen und "Blu Ray" ist das Medium, auf dem "Batman Begins" vorliegt.

Dann nenn das verd***te Array doch bitte cells und nicht movies!!1!!elf!1

Nach dem Filter-Aufruf hast Du dieses Array:

[
    {
      content: 'Batman Begins',
      col: 1,
      row: 1
    },
    {
      content: 'Blu Ray',
      col: 2,
      row: 1
    }
]

und der map-Aufruf wird nun wiederum auf jeden einzelnen Eintrag darin angewendet. Zuerst auf die Namensspalte (col:1), dann auf die Medienspalte (col:2).

Aber ich glaube, das willst Du nicht. Du möchtest das Filterergebnis zu einem einzigen Objekt zusammensetzen. Dafür ist map ungeeignet. Mit map wandelt man einen Array-Eintrag in einen neuen Wert um.

Du möchtest statt dessen mehrere Array-Einträge zu einem Objekt aggregieren:

{
   movie: "Batman Begins",     /* content für col:1 */
   medium: "Blu Ray"           /* content für col:2 */
}

und vermutlich hast Du in der Realität noch ein paar Spalten mehr.

Deine Steuerschleife am Ende ist dann auch unpassend, denn

for (i = 0; i < movies.length; i++) {
}

würde ja einen Durchlauf pro Spreadsheet-ZELLE und nicht pro Spreadsheet-ZEILE machen.

Man kann das Problem mit der filter-Methode lösen, aber dann

  • benenne movies in allMovieCells um
  • erzeuge ein leeres Array movies (nicht items, bitte) für das Ergebnis.
  • finde zunächst den maximalen Wert für "row" in allMovieCells
  • Lass eine Schleife von 1 bis maxRow laufen
    • Filtere alle Zellen zu dieser Row-Nummer heraus. Das Array nenn ich mal cellsForOneMovie - kannst es anders nennen wenn Du willst...
    • Verteile die Werte aus dem Spalten auf die passenden Properties eines Objekts - das kann man abstrakt oder primitiv bauen...
    • Hänge dieses Objekt an dein movies Array an (push)

Ergebnis:

[
   {
     movie: "Batman Begins",
     medium: "Blu Ray" 
   },
   {
     movie: "The Dark Night",
     medium: "Blu Moray" 
   }
]

Zum Verteilen kannst Du eine Hilfsfunktion bauen, die Dir aus einem Array von Zellen den Wert der Zelle mit einer bestimmten Spaltennummer heraussucht.

let movie = {
   movie: getCellValue(cellsForOneMovie, 1),
   medium: getCellValue(cellsForOneMovie, 2)
}

function getCellValue(cells, col) {
   // das kriegst Du selber hin
}

Wenn Du viele Zellen für einen Film hast, ist das lästig. Man könnte auch ein Array aufbauen, das den Spaltennummern Namen zuordnet. Ein Dummy-Eintrag vorneweg, weil JS-Arrays ja mit 0 beginnen.

const columnNames = [ '', 'movie', 'medium', 'erschienen', 'regisseur', 'prodKosten' ],
      maxColumn = columnNames.length - 1;

let movie = { };
for (let cell of cellsForOneMovie) {    // for..of nicht im Internet Explorer!
   if (cell.col >= 1 && cell.col <= maxColumn) {
      colName = columnNames[cell.col];
      movie[colName] = cell.content;
   }
}

Für diesen Weg brauchst Du kein Durchsuchen der Zellen nach Spaltennummern, du ordnest über columnNames direkt die Spaltennummern einem Propertynamen zu.

Rolf

--
sumpsi - posui - obstruxi