Javascript Set – Sammlung von eindeutigen Elementen

set – Sammlung von Werten, ähnlich wie Array

Javascript Set-Objekte sind Sammlungen von Werten eines beliebigen Typs. Die Werte müssen allerdings eindeutig sein. In einem Set darf kein Wert mehrfach vorkommen. Mit einem Set lassen sich z.B. doppelte Werte von Arrays ausklammern.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

Set erzeugen

Während Arrays Sammlungen beliebiger Elemente sind, die beliebig oft im Array vorkommen dürfen, sind Sets Sammlungen, in denen jeder Wert nur einmal vorkommen kann.

let set = new Set (["Hund", "Katze", "Maus"]);

oder 

let arr = ["Hund", "Katze", "Maus", "Katze"];
let set = new Set (arr); // die doppelte Katze ist entfernt

oder 

const set = new Set();
set.add ("Hund")
.add ("Katze")
.add ("Maus");

Javascript iteriert über die Elemente eines Sets wie über ein Array und behält die Ordnung bei: Die Elemente werden in der Reihenfolge durchlaufen, in der sie hinzugefügt wurden.

for of iteriert über iterierbare Objekte (array, map, set, aber auch über nodeLists und HTMLCollections).

for (const item of set) {
	console.log (item);
}

Die Zahl der Elemente eines Sets ist size, nicht length wie bei Arrays. Arrays und Strings sind indexierbar und haben length, Sammlungen haben size.

Die wichtigsten Operationen auf Arrays sind Element hinzufügen, löschen und prüfen, ob ein Element bereits im Array liegt.

Bevor ES6 mit Sets daherkam, wurden Sets durch Arrays und einfache Objekte realisiert. Bei Arrays hätten wir manuell prüfen müssen, ob der neue Wert "cyan" schon vorhanden ist.

let arr = ["rot", "grün", "blau", "olive", "gelb"];

// Element aus dem Array löschen
arr = arr.filter (elem => elem !== "blau");
console.log (arr)

// neues Element in Array einfügen
arr = arr.filter (item => item !== "cyan").concat("cyan");
console.log (arr)

// Prüfen, ob "grün" im Array ist
console.log (arr.includes("grün")); // true

Die Array-Methoden hätten alle Elemente des Arrays durchlaufen. Javascript Set-Methoden berücksichtigen automatisch, dass keine doppelten Werte entstehen.

let aset = new Set ([200, 700, 50, 100]);
aset.delete (700);
console.log (aset);

aset.add(150);
console.log (aset);

console.log(aset.has(150)); // true
console.log(aset.has(70)); // false

Set Datentypen

In ein Set können beliebige Datentypen gesetzt werden: Number, String, Boolean und selbst Arrays.

let arr = [117, 14, 228, 92, 92, 117, 18, 22, 117, 19, 92];
let set = new Set (arr);
console.log ('Array size', arr.length);
console.log ('Set size', set.size);
[Log] Array size – 11 (sets.html, line 185)
[Log] Set size – 7 (sets.html, line 186)

Das Array enthält doppelte Werte: Im Javascript Set werden sie ausgemustert und nicht mitgezählt.

Array Set und Json-Arrays

Eine häufige vorkommende Datenstruktur ist ein Json-Array von Objekten – hier wird Set Duplikate nicht entfernen. Set entscheidet bei strikt einfachen Datentypen wie String, Boolean und Number, ob ein Element ein Duplikat ist, nicht aber bei Objekten. Für Set ist jedes Objekt ein einzigartiges Element.

JSON.stringify wandelt Objekte in Strings um, unter denen Set Duplikate erkennt und ausscheidet.

const images = [
	{ "img": "tasse.jpg", "size": 104, width: 1024, "os": true },
	{ "img": "wald.jpg", "size": 182, width: 900, "os": false },
	{ "img": "nordsee.jpg", "size": 92, width: 1460, "os": true },
	{ "img": "tasse.jpg", "size": 104, width: 1024, "os": true }
];

const uniqueImgStg = new Set(images.map(JSON.stringify));
const uniqueImgStgArr = Array.from(uniqueImgStg);
const uniqueImgObj = uniqueImgStgArr.map(JSON.parse);

console.log (uniqueImgObj);
Array (3)
0 {img: "tasse.jpg", size: 104, width: 1024, os: true}
1 {img: "wald.jpg", size: 182, width: 900, os: false}
2 {img: "nordsee.jpg", size: 92, width: 1460, os: true}

Einfach new Set reicht aber nicht, denn new Set erzeugt ein Objekt – für JSON wird ein Array von Objekten gebraucht.

Das erledigt Array.from(uniqueImgStg) und am Ende erzeugt JSON.parse das Array von eindeutigen Objekten.

Diese einfache Methode hilft aber nur, wenn alle Objekte innerhalb des JSON-Arrays die gleichen Elemente enthalten und die Elemente gleich angeordnet sind. Also nicht so:

const images = [
	{ "img": "tasse.jpg", "size": 104, width: 1024, "os": true },
	{ "img": "tasse.jpg", "os": true, "size": 104, width: 1024 },
	{ "img": "tasse.jpg", "size": 104, width: 1024 }
];

Weitere Set-Operationen

Ein paar typischer Operationen wie Schnittmenge und Vereinigung fehlen in Sets.

  • Schnittmenge von Set A und Set B,
  • die Vereinigung von Set A und Set B
  • Untermenge

Wenn sie gebraucht werden, wandelt man die Sets mit dem Spread-Operator in Arrays um, führt die Operation auf den Arrays durch und konvertiert das Ergebnis wieder in ein Set.

Schnittmenge zweier Arrays
let newArr = ["Hund", "Katze", "Maus", "Pferd", "Ochse", "Esel"];
let newBrr = ["Adler", "Huhn", "Maus", "Esel"];

function schnittmenge (a, b) {
	return a.filter (item => b.includes (item));
}

console.log ("Array Schnittmenge " , schnittmenge (newArr, newBrr));

Sets sind iterierbar, also kann der spread-Operator sie in Arrays umwandeln.

Schnittmenge zweier Sets
let a = new Set(["Hund", "Katze", "Maus", "Pferd", "Ochse", "Esel"])
let b = new Set(["Adler", "Huhn", "Maus", "Esel"])
let intersect = new Set([...a].filter(i => b.has(i)));

console.log ("Set Schnittmenge ", intersect);