当数组达到特定长度时删除javascript数组的最后一个元素

Posted

技术标签:

【中文标题】当数组达到特定长度时删除javascript数组的最后一个元素【英文标题】:Drop last element of javascript array when array reaches specific length 【发布时间】:2015-09-10 11:09:51 【问题描述】:

我想在 javascript 中缓存一些数据,但是缓存应该限制为例如 10 个元素。

我可以将对象放在 javascript 数组中,但是将数组限制为 10 个元素的最佳方法是什么?

例子:

function getData(dataId)  return new NextDataObject(dataId); 

var array = new Array();

array.push(getData(0));
array.push(getData(1));
(...)
array.push(getData(10)); // this should result in dropping "oldest" data, so getData(0) should be removed from the array, so that in array there are only 10 objects at maximum

是否应该手动编写这种机制(例如使用 splice()?)还是有更好的方法在 javascript 中实现这种“缓存”结构?

顺便说一句:在这种特殊情况下,我使用的是 angular。

【问题讨论】:

必须是数组还是对象? 【参考方案1】:

覆盖缓存数组的push 函数。

var array = new Array()
array.push = function ()
    if (this.length >= 10) 
        this.shift();
    
    return Array.prototype.push.apply(this,arguments);

Plunker


为了使其更可重用,我创建了一个返回此类数组的新实例的方法(基于上述代码)。

function getArrayWithLimitedLength(length) 
    var array = new Array();

    array.push = function () 
        if (this.length >= length) 
            this.shift();
        
        return Array.prototype.push.apply(this,arguments);
    

    return array;



var array = getArrayWithLimitedLength(10);

【讨论】:

我认为这不是最好的方法,因为如果他有另一种情况,数组可以超过 10 的长度,push() 仍然会将其限制为 10.. @Guinn 相当不错的解决方案。而在“数组可以超过的另一种情况”中,只需使用带有原型原始推送的干净数组实例。 @Michael 你想使用shift 而不是unshift 啊,它只适用于这个特定的数组,我一定错过了。我的坏 这个方案很棒,因为它不修改Array对象的原型,简单【参考方案2】:

要从数组中删除 first 元素,请使用 shift:

if (arr.length > 10) 
    arr.shift(); // removes the first element from an array 

【讨论】:

第二个答案xD @Tushar,我猜你的第二个答案是不正确的,它实际上是帮助我们删除第一个元素的“移位”。【参考方案3】:

这个对象怎么样?

function Cache(maxLength) 
  this.values = [];

  this.store = function(data) 
    if(this.values.length >= maxLength) 
      this.getLast();
    
    return this.values.push(data);
  

  this.getLast = function() 
    return this.values.splice(0,1)[0];
  


cache = new Cache(3);
// => Cache values: Array[0]
cache.store(1)
// => 1
cache.store(2)
// =>2
cache.store(3)
// => 3
cache.store(4)
// =>3
cache.values
// => [2, 3, 4]
cache.getLast()
// => 2
cache.values
[3, 4]

【讨论】:

自定义数据结构可能是这种情况下的最佳解决方案。易于测试且非常灵活。 谢谢。我不认为为这种功能更改 Array 原型是一个好习惯。 (如果其他库也这样做呢?)我也相信创建良好的、包含的、OO 代码单元是一种很好的做法。然后它们具有适应性、可重用性,并且如果您需要更改它们的功能,它们具有您可以遵循的接口。 不错的解决方案(我也在考虑),但是@Michael 提出的单个数组实例的覆盖方法要好得多,因为它很简单。 确实很优雅,占地面积小。如果您的代码库小而简单,并且会保持这种状态,那么它是一个很好的解决方案。如果您预见到将来需要多个缓存或更复杂的缓存行为,则需要对其进行扩充。【参考方案4】:

您可以在Array.prototype 中创建新方法来模拟您的需求。

Array.prototype.push_with_limit = function(element, limit)
  var limit = limit || 10;
  var length = this.length;
  if( length == limit )
    this.shift();
  
  this.push(element);


var arr = []
arr.push_with_limit(4); // [4]
arr.push_with_limit(9); // [4, 9]
....
// 11th element
arr.push_with_limit(3); // [9, ..., 3]  10 elements

【讨论】:

这无需太多代码即可完成工作。不过,我倾向于回避更改基本 JS 对象的原型……此类更改可能会与执行相同或相似操作的其他代码交互。另外,如果我以后想增加更多的复杂性,我要么不得不更多地污染 Array 的原型,要么改变这个功能在整个代码库中的使用方式。那和我是一个彻头彻尾的鸡。 Bk-arrrrk. 好的,但我不喜欢这样,因为它改变了 Array 对象的原型【参考方案5】:

简单的定长队列:

Array.prototype.qpush = function( vals, fixed ) 
    if (arguments.length) 
        if (Array.isArray(vals)) 
            for (var v of vals) 
                this.push(v);
            
         else 
            this.push(vals);
        
        var _f = (typeof this.fixed != undefined) ? this.fixed : 0;
        if (typeof fixed != undefined) 
            _f = (Number(fixed)===fixed && fixed%1===0 ) ? fixed : _f;
        
        this.fixed = _f;
        if (this.fixed>0) this.splice(0, this.length - _f);        
    


var q = new Array();
q.push(0);
q.qpush( [1, 2, 3], 10 );
q.qpush( [4] );
q.qpush( 5 );
q.qpush( [6, 7, 8, 9, 10, k:"object" ] );
console.log(q);

【讨论】:

好的,但我不喜欢这样,因为它改变了 Array 对象的原型【参考方案6】:
if(array.length == 10) 

    array.splice(0, 1);
    // this will delete first element in array

【讨论】:

【参考方案7】:

如果您使用array.length 检查数组是否已达到 10 个条目,则只需在推送新元素之前删除第一个元素。正如 Tushar 所说,这可以通过多种方式完成,array.shift() 将是最快的,但您也确实可以使用array.splice()

看起来像这样:

if(array.length > 10) 
    array.shift();
    array.push(getData(10));

顺便说一句,我建议您不要使用var array = new Array(),而是直接使用var array = [];。这是因为 Javascript 中的 new 关键字有时会产生不好的副作用。例如,如果您想创建一个包含 1 个元素为数字的数组,并且您使用 var arr = new Array(12);,则将创建一个包含 12 个未定义元素的数组。而var arr = [12]; 将创建一个包含 1 个元素的数组,即数字 12。

但我想这是一件需要考虑的小事..

【讨论】:

这应该作为对问题的评论而不是答案发布。 呃,为什么?我回答了你的问题不是吗?如果您考虑文本答案而不是代码,则可以复制粘贴不合适,我更新了您可以复制粘贴的代码〜_〜 我给了“加一”,但请注意我没有问我应该如何初始化 Array。我问我应该如何限制,你从“课程”开始你的答案如何限制数组......你可以把它放在答案的末尾或顺便说一句,但你不应该以此开始你的答案。顺便说一句:代码片段无关紧要。您可以根据此编辑您的答案,就可以了。 那么,你去吧【参考方案8】:

你可以使用一个对象来代替......

var obj = ; //your cache object
obj[window.performance.now()] = getData(val); //add value, index by microsecond timestamp
if(Object.keys(obj).length > 10) // then if the length ever gets bigger than 10..
 var array = Object.keys(obj).sort(); //sort the properties by microsecond asc
 delete obj[array[0]]; //delete the oldest one   

这是一个展示其工作原理的 jsFiddle 示例:https://jsfiddle.net/uhkvk4mw/

【讨论】:

感谢您的代码,但对于如此简单的任务恕我直言,这太复杂了。【参考方案9】:

只要检查是否达到长度然后弹出它

if(arr.length > someNumber)
arr.pop(); // pop() will remove the last element

【讨论】:

以上是关于当数组达到特定长度时删除javascript数组的最后一个元素的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法JavaScript描述——链表

使用javascript删除对象数组中的特定数组

JavaScript如何从数组中删除特定数据

当对象键javascript中的数组字符串匹配时删除对象

javascript中的链表结构

javascript中的链表结构