【问题标题】:Remove element from array on timeout Node.js超时Node.js从数组中删除元素
【发布时间】:2017-02-01 20:27:22
【问题描述】:

我有一个非常动态的数组,总是有新元素,而其他元素被删除了。问题是,有时,在某些情况下,有些元素可能永远留在数组中,并且那不是我想要的。每个元素都应在 15 秒内从数组中删除,否则数组应自动删除该元素。

例如,在下面的代码中,我们有一个包含三个元素的数组:

var array = ['e1', 'e2', 'e3'];

5 秒后,我在数组中再添加 2 个元素:

array[3] = 'e4';
array[4] = 'e5';

现在,假设前 3 个元素在下午 12:00:00 插入数组,后两个元素在下午 12:00:05 插入。我希望在下午 12:00:15 删除前 3 个元素,在下午 12:00:20 删除后两个元素......等等......

对于如何解决这个问题有什么想法吗?

【问题讨论】:

  • 你能发布你的代码吗?当我们不知道您在做什么时,很难说如何解决。
  • 我无法发布整个代码,因为它太大太复杂,但我添加了一个简单的示例来解释我的“问题”。

标签: javascript arrays node.js


【解决方案1】:

您需要在将值插入数组时存储一个引用,以便能够在某个点删除它们。您可能希望为此使用纯 JavaScript 对象:

var map = {};

map[Date.now()] = ['a', 'b'];
console.log(map);

setTimeout(function() {
  map[Date.now()] = ['c', 'd'];
  console.log(map);
}, 5000);

setInterval(function() {
  var times = Object.keys(map);
  
  times.forEach(function(time) {
    if(Date.now() > (+time + 14000)) {
      delete map[time];
    }
  });
  
  console.log(map);
}, 1000);

本质上,我将时间保存为键,将项目数组保存为值。 (点击上面的“Run code sn -p”查看控制台输出,看看它的行为如何)。

基本上我们设置了一个每秒运行的“cron 作业”(简单的setInterval)并检查创建密钥的时间是否小于 14 秒前(不是 15 秒,因为 cron 作业每秒运行一次) .然后它只是从对象中删除该键。

【讨论】:

  • 只要您不需要同时插入多个项目,这将起作用。
【解决方案2】:

通常,当您将项目添加到数组时,您不想假设它们将存在的位置。代替array[3] = 'e4',使用array.push('e4')。这将使您的生活更轻松,并且不易出错。

因为您需要将时间与每个项目相关联,所以使用对象代替字符串可能是明智的。

// create the array and push some objects into it
var array = []
array.push({createdAt: Date.now(), value: 'asdf'})
array.push({createdAt: Date.now(), value: 'asdf'})

然后,在一段时间内,您可以检查每个对象的createdAt 值,并决定是否要将它们踢出数组。

var maxLifespan = 5000
// check once per second
setInterval(function checkItems(){
    array.forEach(function(item){
        if(Date.now() - maxLifespan > item.createdAt){
            array.shift() // remove first item
        }
    })
}, 1000)

使用array.shift() 假设您将始终将新项目推到数组的末尾,因此它们将始终按时间顺序排序。

如果您需要不按时间顺序对数组进行排序,那么您需要使用一种方法来删除数组中特定索引处的元素(提示:NOT delete)。使用array.splice 来实现这一点。

【讨论】:

  • 这个解决方案看起来不错,但你能告诉我如何手动按值删除项目吗?因为有时,用户会在超时之前删除元素。
  • 使用 array.splice 从数组中删除元素。我已经扩展了答案。
  • 嗯,我不能使用 array.splice,因为我不知道要删除的值在什么位置。比如我有两个值,“v1”和“v2”,我不知道v1是在位置0还是1。我只知道数组中包含v1的项不再需要了。跨度>
  • 查看其他 SO 答案:stackoverflow.com/questions/8668174/…
【解决方案3】:

您可以使用如下函数向数组中添加元素:

function insert(array, element) {
    array.push(element);

    setTimeout(() => {
        const index = array.indexOf(element);
        if (index >= 0) {
            array.splice(index, 1);
        }
    }, 15000);
}

这样,无论如何您都可以确保在大约 15 秒后删除该元素。显然,它可以 100% 正确地处理对象/数组(引用类型),但是如果您存储像字符串或数字这样的原语,那么如果您在数组中有超过 1 个这样的原语值,您最终可能会删除该值的另一​​个副本,但最终每个元素都会在大约 15 秒后被删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2016-03-08
    相关资源
    最近更新 更多