Javascript 获取插入到集合中的最后一个值

Javascript 获取插入到集合中的最后一个值,javascript,ecmascript-6,Javascript,Ecmascript 6,表示JavaScriptSet对象保留元素的插入顺序: 集合对象是值的集合,可以按插入顺序迭代其元素 是否有办法将最后一项插入集合对象 var s = new Set(); s.add("Alpha"); s.add("Zeta"); s.add("Beta"); console.log(getLastItem(s)); // prints "Beta" 编辑 可以实现与Set具有相同接口且具有所需功能的链接集数据结构容器类。请参阅下面的答案。我找不到任何方法来获取从中插入的最后一个值,可能

表示JavaScript
Set
对象保留元素的插入顺序:

集合对象是值的集合,可以按插入顺序迭代其元素

是否有办法将最后一项插入
集合
对象

var s = new Set();
s.add("Alpha");
s.add("Zeta");
s.add("Beta");

console.log(getLastItem(s)); // prints "Beta"
编辑


可以实现与
Set
具有相同接口且具有所需功能的链接集数据结构容器类。请参阅下面的答案。

我找不到任何方法来获取从中插入的最后一个值,可能他们从未打算使用这种方法,但您可以执行以下操作:

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

再想一想,节省空间的解决方案可能是:

function getLastValue(set){
  let value;
  for(value of set);
  return value;
}

const a = new Set([1, 2, 3]);
a.add(10);
console.log('last value: ', getLastValue(a));

是的,有一种方法可以做到这一点,您可以简单地将集合转换为数组并弹出最后一项

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"
一些想法:

  • 考虑使用数组而不是集合。提取数组的最后一个元素很容易,例如

    array[array.length-1];
    array.slice(-1)[0];
    array.pop(); // <-- This alters the array
    
  • 考虑按相反顺序插入项目。然后,您只需要获取集合中的第一项,这样更容易:

    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
    添加的值。更完整的是,它还应该在构建集合时检测最新的值,并在删除最后一项时更新该值

    • 这只是另一种方法

      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"
      

      我已经为
      集合
      创建了一个替换项,它使用底层的
      映射
      重新实现集合的链接功能

      类LinkedSetLink{
      构造函数(值){
      这个值=值;
      this.prev=这个;
      this.next=这个;
      }
      插入之前(项目){
      const prev=item.prev=this.prev;
      const next=item.next=this;
      next.prev=项目;
      prev.next=项目;
      }
      删除(){
      const prev=this.prev;
      const next=this.next;
      next.prev=prev;
      上一个=下一个;
      }
      }
      类链接集{
      构造函数(iterable){
      这个._map=newmap();
      此._pivot=newlinkedSetLink(/*未定义*/);
      如果(可编辑){
      本._addAll(iterable);
      }
      }
      _addAll(可编辑){
      用于(iterable的常数项){
      本条增加(项目);
      }
      }
      民政事务总署(项目){
      返回此。_map.has(项目);
      }
      添加(项目){
      如果(!此._地图有(项目)){
      const link=新的LinkedSetLink(项目);
      此._pivot.insertBefore(链接);
      此.u映射集(项目、链接);
      }
      }
      删除(项目){
      const link=this.\u map.get(项目);
      如果(链接){
      此._映射。删除(项目);
      link.remove();
      }
      }
      清除(){
      这个._map.clear();
      这个。_pivot.next=这个。_pivot.prev=这个。_pivot;
      }
      获取大小(){
      返回此。\u map.size;
      }
      值(){
      返回此项。_map.keys();
      }
      钥匙(){
      返回此.values();
      }
      [符号.迭代器](){
      返回此.values();
      }
      *条目(){
      for(此.values()的常量键){
      屈服[钥匙,钥匙];
      }
      }
      第一(){
      返回此值。\u pivot.next.value;
      }
      最后(){
      返回此值。\u pivot.prev.value;
      }
      }
      函数test1(){
      log(Array.from(新的LinkedSet([“a”、“b”、“c”])).entries());
      }
      函数test2(){
      log(新的链接集([“a”、“b”、“c”).last();
      }
      测试条目
      
      最后测试
      @hege_hegedus-我没有注意到mido的答案,一开始我发布了相同的答案,所以我想我必须想出一些至少有点不同的东西,排列操作符以及如何获取整个条目、键等,我只是好奇:是否有一个简短的语法来耗尽迭代器并在不构建列表的情况下获取最后一个元素?(我的意思是比为该任务编写单独的函数还要短)我认为没有,但我仍然不知道ES2015的所有细节。集合在某种程度上受限于几个原型方法,它必须是ES2015中的其他聪明的东西,使用迭代器等。这是一个糟糕的解决方案。为什么Javascript开发人员从不关心性能或效率?@timmm-为什么很糟糕,在数组中传播
      很可能比其他解决方案快,除了迭代的空
      for…of
      循环。
      Set
      没有获取最后一项的真正方法,也没有索引或内置项,因此要么迭代到最后一项,要么将
      Set
      转换为具有内置项的内容,如数组。除非
      很大,否则性能差异不会明显。没有内置的恒定时间解决方案吗?@hege_hegedus不幸的是,没有,至少我在规范中找不到:(我开始怀疑将
      集合
      转换回
      数组
      的开销。对于大型集合,它可能会或可能不会表现出一些开销。但是,这是有意义的
      。最后一个
      不包括在规范中,因为理论上,集合不需要顺序。在插入顺序中,javascript是否有O(n)设置操作?@Filiphalund Insert、lookup和remove是O(1)。标准要求另外一件事:按插入顺序迭代项目。但不必迭代进行查找。我很确定这不是O(1)。它是否保留了单独的键列表进行迭代,并保留了一棵树进行查找,使迭代成为O(n log n)?@FilipHaglund这些操作可以通过哈希表和链表的组合来实现。设想在每个条目之外有一个“下一项”引用(哈希表基础数组中的索引),并在每个操作上更新该引用。插入和删除为O(1)在链表上。对于查找,使用哈希表。规范仅要求访问时间平均为次线性。具体结构和成本取决于实现。请注意
      s.last()
      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"