Obtenir la dernière valeur insérée dans un Ensemble

La documentation MDN pour Set indique que les objets JavaScript Set conservent l'ordre d'insertion des éléments:

Les objets Set sont des collections de valeurs, vous pouvez itérer ses éléments dans l'ordre d'insertion.

Existe-t-il un moyen d'obtenir le dernier élément inséré dans un objet Set ?

 var s = new Set(); s.add("Alpha"); s.add("Zeta"); s.add("Beta"); console.log(getLastItem(s)); // prints "Beta" 

Je n'ai pu trouver aucune méthode pour obtenir la dernière valeur insérée dans l'ensemble de la spécification ECMA 2015 , peut-être qu'ils n'ont jamais prévu une telle méthode, mais vous pouvez faire quelque chose comme:

 var a = new Set([1, 2, 3]); a.add(10); var lastValue = Array.from(a).pop(); 

Modifier:

À la réflexion, une solution économiquement efficace pourrait être:

 function getLastValue(set){ var value; for(value of set); return value; } var a = new Set([1, 2, 3]); a.add(10); console.log('last value: ', getLastValue(a)); 

Quelques idées:

  • Envisagez d'utiliser un tableau au lieu d'un ensemble. L'extraction du dernier élément d'un tableau est simple, par exemple

     array[array.length-1]; array.slice(-1)[0]; array.pop(); // <-- This alters the array 

    Si vous avez vraiment besoin d'un ensemble, vous pouvez le convertir en un tableau lorsque vous souhaitez extraire le dernier élément, mais cela coûtera du temps et de l'espace.

  • Iterate l'ensemble manuellement. Cela coûtera du temps, mais pas autant d'espace que de copier dans un tableau. Par exemple (il y a probablement des façons plus élégantes de le faire)

     var set = new Set([1, 2, 3]); var iter = set.values(), prev, curr; do { prev = curr; curr = iter.next(); } while(!curr.done) var last = prev.value; // 3 
  • Envisager d'insérer les éléments dans l'ordre inverse. Ensuite, il vous suffit d'obtenir le premier élément dans l'ensemble, et c'est plus facile:

     set.values().next().value; 
  • Sous-classe Set pour ajouter cette nouvelle fonctionnalité:

     class MySet extends Set { add(value) { super.add(value); this.last = value; } } var set = new MySet(); set.add(1); set.add(2); set.add(3); set.last; // 3 

    Notez que cela ne détectera que les valeurs ajoutées avec add . Pour être plus complet, il devrait également détecter la dernière valeur lorsque l'ensemble est construit et mettre à jour la valeur lorsque le dernier élément est supprimé.

Oui, il existe un moyen de le faire, vous pouvez simplement convertir l'ensemble en un tableau et le pop du dernier élément

 function getLastItem(_set) { return [..._set].pop(); } 

Pour obtenir des clés / valeurs, etc., vous pouvez le faire

 return [..._set.entries()].pop(); // the entire entry return [..._set.keys()].pop(); // the key only return [..._set.values()].pop(); // the value only 

Si vous ne voulez pas créer un tableau, vous devrez probablement itérer et obtenir la dernière valeur, comme celle-ci

 var last; s.forEach(k => { last = k }); // last === "Beta" 

VIOLON

Une autre approche.

 Set.prototype.last = function(){ return new Set().add( [...this].pop() ); } Set.prototype.lastKey = function(){ return [...this.keys()].pop(); } Set.prototype.lastValue = function(){ return [...this.values()].pop(); } var lastSet = s.last(); // "Beta" var lastKey = s.lastKey(); // "Beta" var lastValue = s.lastValue(); // "Beta" 
 indexOfLastItem=s.length-1; return(s[indexOfLastItem]); 

J'ai créé un remplacement pour Set , qui re-met en œuvre les fonctionnalités liées de l'ensemble, en utilisant une Map sous-jacente.

 class LinkedSetLink { constructor(value) { this.value = value; this.prev = this; this.next = this; } insertBefore(item) { const prev = item.prev = this.prev; const next = item.next = this; next.prev = item; prev.next = item; } remove() { const prev = this.prev; const next = this.next; next.prev = prev; prev.next = next; } } class LinkedSet { constructor(iterable) { this._map = new Map(); this._pivot = new LinkedSetLink(/* undefined */); if (iterable) { this._addAll(iterable); } } _addAll(iterable) { for (const item of iterable) { this.add(item); } } has(item) { return this._map.has(item); } add(item) { if (!this._map.has(item)) { const link = new LinkedSetLink(item); this._pivot.insertBefore(link); this._map.set(item, link); } } delete(item) { const link = this._map.get(item); if (link) { this._map.delete(item); link.remove(); } } clear() { this._map.clear(); this._pivot.next = this._pivot.prev = this._pivot; } get size() { return this._map.size; } values() { return this._map.keys(); } keys() { return this.values(); } [Symbol.iterator]() { return this.values(); } *entries() { for (const key of this.values()) { yield [key, key]; } } first() { return this._pivot.next.value; } last() { return this._pivot.prev.value; } } function test1() { console.log(Array.from(new LinkedSet(["a", "b", "c"]).entries())); } function test2() { console.log(new LinkedSet(["a", "b", "c"]).last()); } 
 <button onclick="test1()">test entries</button> <button onclick="test2()">test last</button>