Получить последнее значение, вставленное в набор
Документация MDN для Set говорит о том, что JavaScript Set
объекты сохраняют порядок вставки элементов:
Заданные объекты являются коллекциями значений, вы можете перебирать их элементы в порядке вставки.
Есть ли способ вставить последний элемент в Set
объект?
var s = new Set();
s.add("Alpha");
s.add("Zeta");
s.add("Beta");
console.log(getLastItem(s)); // prints "Beta"
редактировать
Возможно реализовать класс контейнера структуры данных Linked Set, который имеет тот же интерфейс, что и Set
и имеет желаемую возможность. Смотрите мой ответ ниже.
9 ответов
Мне не удалось найти какой-либо метод для получения последнего значения, вставленного в набор из спецификации ECMA 2015, возможно, они никогда не предполагали такой метод, но вы можете сделать что-то вроде:
var a = new Set([1, 2, 3]);
a.add(10);
var lastValue = Array.from(a).pop();
Редактировать:
Вторая мысль: эффективное решение может быть:
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));
Некоторые идеи:
Рассмотрите возможность использования массива вместо набора. Извлечь последний элемент массива легко, например
array[array.length-1]; array.slice(-1)[0]; array.pop(); // <-- This alters the array
Если вам действительно нужен набор, вы можете преобразовать его в массив, когда вы хотите извлечь последний элемент, но это будет стоить времени и пространства.
Повторите набор вручную. Это будет стоить времени, но не так много места, как копирование в массив. Например (есть, вероятно, более элегантные способы сделать это)
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
Попробуйте вставить элементы в обратном порядке. Тогда вам нужно только получить первый предмет в наборе, и это проще:
set.values().next().value;
Подкласс
Set
чтобы добавить эту новую функциональность: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
Обратите внимание, что это будет обнаруживать только значения, добавленные с
add
, Чтобы быть более полным, он также должен определять последнее значение при создании набора и обновлять значение при удалении последнего элемента.
Да, есть способ сделать это, вы можете просто преобразовать набор в массив и всплеск последнего элемента
function getLastItem(_set) {
return [..._set].pop();
}
чтобы получить ключи / значения и т.д., вы можете сделать
return [..._set.entries()].pop(); // the entire entry
return [..._set.keys()].pop(); // the key only
return [..._set.values()].pop(); // the value only
Если вы не хотите создавать массив, вам, вероятно, придется выполнить итерацию и получить последнее значение, например
var last; s.forEach(k => { last = k }); // last === "Beta"
Просто другой подход.
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"
Я создал замену для Set
, который повторно реализует связанную функциональность набора, используя базовый Map
,
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>
Простое решение, ноO(N)
:
const getLastValueFromSet = (set) => {
for (var value of set);
return value;
}
Метода доступа к последнему элементу нет, но вы можете сделать это следующим образом.
let setOfNumbers = new Set([10]);
setOfNumbers.add(20).add(2);
let lastValue = [...setOfNumbers].pop()
Как упоминалось ранее, для этого есть много способов.
Если вы хотите изменить основное значение переменной в памяти:
s = new Set()
s.add('banana')
s.add('apple')
//acts like array.pop()
// removes the first item in the set
s.delete(s.values().next().value)