JavaScript中的数组压缩

6

JavaScript中与Ruby的Array#compact相当的是什么?

长篇版本...我按照blog.nemikor.com上的示例进行操作。他的最后一个示例关闭旧请求,但是pendings继续填充过时的请求。这对我来说看起来像是内存泄漏。

我的解决方案是使用下面的filter迭代pendings,但这似乎可能存在pendings.pushpendings = pendings.filter之间的竞争条件。我是多虑了吗?如果存在竞争条件,我该如何解决?

var pendings = [];

// there is a route
app.get('/some/path', function (request, response) {
  pendings.push({
    response: response,
    requestedAt: new Date().getTime()
  });
});

setInterval(function () {
  var expiration = new Date().getTime() - (1000 * 30);
  pendings = pendings.filter(function (pending, index) {
    if (pending.requestedAt > expiration) {
      return true;
    } else {
      pending.response.writeHead(408, { 'Content-Type': 'text/plain' });
      pending.response.end('');
    }
  });
}, 1000);

1
紧凑型行为 - Zabba
如果需要,可以查看MDC文档中关于filter的内容。 - RobG
请点击Zabba的链接以获取标题问题的答案... - AShelly
4个回答

2
您在JavaScript中没有线程,因此不可能出现竞态条件。所有代码都是顺序执行的,并且只有在运行完成后才会转移控制权。因此,在任何其他函数触及pendings之前,您的间隔函数将运行到完成。
这也适用于像setTimeoutsetInterval之类的东西。
作为一个实验:如果您使用setTimeout设置了1秒后触发的超时。然后在此之后编写一个阻塞2秒钟的while循环,您的超时将在此之后触发,时间远远超过1秒。
某些粗略的内容:
var timer = setTimeout(function () {
    alert("hi!");
}, 1000);
var now = new Date();
var till = new Date(now + 2);
while(new Date() < till) {}   // block for 2 seconds

2
一段老的帖子,但它值得回答原始问题: JavaScript 中等价于 Ruby 的 Array#compact 是什么?

list1 = [null, 'no', 'nulls', null]

// With plain JS
jsFilter = list1.filter(function (obj) { return obj })

// With ES6
let filtered = list1.filter((obj) => obj)

//> (2) ["no", "nulls"]

console.log(es6Filter)

但是需要注意的是,因为:
filter() 方法会为数组中的每个元素调用一个提供的回调函数,并构造一个新数组,其中包含所有使回调函数返回值为真的值。

falsey = [false, 0, 0n, '', NaN, null, undefined]
truthy = [true, 1, ' ']

list2 = ['returns', 'only', 'truthy', 'values'].concat(truthy).concat(falsey)

let filtered = list2.filter((obj) => obj)

//> (7) ["returns", "only", "truthy", "values", true, 1, " "]

console.log(filtered)

为了使其像 Ruby 的 compact 一样工作,您可以这样做:

falsey = [false, 0, 0n, '', NaN, null, undefined]
truthy = [true, 1, ' ']
list3 = ['works', 'like', "Ruby's", 'compact'].concat(truthy).concat(falsey)

let them_go = [null, undefined] // Just a fun with variable names
let filtered = list3.filter((obj) => { return !them_go.includes(obj) })

//> (12) ["works", "like", "Ruby's", "compact", true, 1, " ", false, 0, 0n, "", NaN]

console.log(filtered)

如果您想从数组中删除所有空元素(空字符串、数组和对象),您可以在这里查看我的答案 -> https://dev59.com/vnVC5IYBdhLWcg3weBA-#59905255 参考资料:

2

您可能想要查看Underscore.js库
http://documentcloud.github.com/underscore/

这提供了许多有用的低级函数来处理集合、数组和对象。它包括一个compact函数(虽然我认为它的目的与您寻找的不同),以及一个filter函数。


感谢您推荐underscore.js。 我查看了它,但由于我还没有需要它,所以没有考虑过它。Node.js提供了一个筛选方法,并且根据@frits-van-campen的回答,我不必担心竞争条件。 :) - ravinggenius

1
只要您不进行I/O操作,也就是仅进行内存操作,就能保证不会被打断(由于事件循环的性质)。
因此,如果您的集合太长(例如数千个或更多),请注意,因为这可能会阻塞事件循环一段时间,导致其他请求无法被服务。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接