MDN documentation for Set表示JavaScript Set
对象保留了元素的插入顺序:
设置对象是值的集合,您可以按插入顺序迭代其元素。
有没有办法将最后一项插入Set
对象?
var s = new Set();
s.add("Alpha");
s.add("Zeta");
s.add("Beta");
console.log(getLastItem(s)); // prints "Beta"
修改的
可以实现与Set
具有相同接口并具有所需功能的链接集数据结构容器类。请参阅下面的答案。
答案 0 :(得分:19)
我无法找到任何方法来从ECMA 2015 Specification的集合中插入最后一个值,可能他们从未想过这样的方法,但你可以这样做:
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));
答案 1 :(得分:14)
一些想法:
考虑使用数组而不是集合。提取数组的最后一个元素很简单,例如
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
添加的值。为了更完整,它还应该在构造集合时检测最新值,并在删除最后一个项目时更新该值。
答案 2 :(得分:11)
是的,有办法做到这一点,你可以简单地将集合转换为数组并弹出最后一项
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"
答案 3 :(得分:3)
只是另一种方法。
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"
答案 4 :(得分:2)
我创建了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());
}
&#13;
<button onclick="test1()">test entries</button>
<button onclick="test2()">test last</button>
&#13;