【问题标题】:Javascript - functional approach to remove empty elements from end of arrayJavascript - 从数组末尾删除空元素的功能方法
【发布时间】:2015-03-05 18:10:56
【问题描述】:

输入数组如下:

var arr = ["some", "", "", "value", "", "", ""];

我需要从尾部删除空元素。所以预期的输出是:

["some", "", "", "value"]

我知道一个无聊的反向循环会起作用,或者 pop() 直到它到达第一个非空元素。例如:

while(arr.pop() === "")

但是,只是为了好玩,我希望看到一种同样或更有效(如果可能)功能的方法。

我的第一个功能想法是用 reverse -> reduce -> reverse 来实现它。但是它似乎很复杂,所以我想看看是否有人有更好的方法。

var arr = ["some", "", "", "value", "", "", ""];

var result = arr.reverse()
    .reduce(function (a, b) {
        if (b != "")
            a.addallnext = true;

        if (a.addallnext === true)
            a.result.push(b);

        return a;
    }, {
        addallnext: false, result: []
    }).result.reverse();

这是我的小提琴:

http://jsfiddle.net/fy4cuspq/1/

我希望算法使用内置数组方法,但如果你有一些很棒的自定义方法或类似的方法可以添加到原型中,那就太好了。

注意:我的目标不是用效率较低的函数式方法等替代更有效的迭代方法……这只是对功能美的探索;)

【问题讨论】:

  • 所以您想采用O(n) 算法(向后循环或弹出直到得到非空结果)并用O(3n) 算法(反向、减少、反向)替换它?跨度>
  • 当然不是。正如我所说,这只是为了好玩;)探索功能方法。
  • @MattBurland 两种算法都是 O(n)。
  • @JLRishe:正确,我说错了。实际上,如果您考虑最佳情况下的性能,则向后循环是O(1)(没有空元素),而reverse、reduce、reverse 仍然是O(n)

标签: javascript arrays algorithm


【解决方案1】:

您可以使用reduceRight。我正在使用Array.prototype.concat 来保持代码没有突变。另外,我依靠结果的长度来查看何时停止删除空字符串。

var reducedArray = arr.reduceRight(function (result, a) {
  return result.length === 0 && a === ""
       ? result
       : [a].concat(result);
}, []);

【讨论】:

  • 我不知何故忘记了 reduceRight :) 这是一个好方法。谢谢!
  • 我的头脑刚刚在这里爆炸。你能逐行解释吗?看起来很有趣(我在返回时很挣扎,哈哈)
  • @briosheje 实际上很简单。 reduceRight 从右到左处理元素(逆序)。 result 变量在 reduceRight 函数中初始化为 [ ] ,无论如何回调都应该返回它。但是,如果右边的元素是空的,它们将不会被添加到结果中(这就是为什么他只返回结果,而不是在当前元素前面加上-a-),如果 a 不为空,它将被添加到前面结果 [ ] 使用 concat ;) 使用前置方法,他避免了再次反转()数组;)
【解决方案2】:

如果最后一个元素是空字符串,那么简单地删除它怎么样?

var arr = ["some", "", "", "value", "", "", ""];

while ( arr.getLast() == "" )  arr.pop();

(编辑:OP 刚刚编辑了这个问题,说他不想要这种特殊方法..)

【讨论】:

  • 这不正是 OP 在他们的问题中提出的吗?
  • 查看编辑历史,从一开始就存在:I know a boring reverse loop would work, or pop() until it comes to the first non-empty element
  • 没看到……哦,好吧
【解决方案3】:

我认为我有一个比 @Ionut 更有效率的人,虽然他看起来更漂亮。

perf (22%) | fiddle

arr.reverse();
arr.some(function(elem, i, array) {
  if (elem) {
    array.splice(0, i);
    return true;
  } else return false;
});
arr.reverse();

希望对您有所帮助! :)

【讨论】:

  • 这是一个隐式全局吗?吉普车!
  • @JLRishe 不,不是,你什么都没看到。
【解决方案4】:

问题归结为找到不以空字符串结尾的初始子数组的长度。由于 Javascript 的 Array.prototype.reduce 可以提供数组的当前索引,这可以通过简单的reduce 来实现:

function trim(arr) { 
  return arr.slice(0,arr.reduce(function(i,b,j){return b===""?i:j+1},0))
}

reduce 中,每个点的第一个参数是当前修剪段的长度。由于第三个参数是当前的index,它需要递增以产生当前的length

如果reduce 没有为回调提供额外的参数,您可以通过减少传递一对值来实现(仍然在功能上,但不太清晰):

function trim(arr) { 
  return arr.slice(0,arr.reduce(
      function(ij,b){
          return [b===""?ij[0]:ij[1]+1,
                  [ij[1]+1]
      },[0,0])[0])
}

【讨论】:

    【解决方案5】:

    我知道 stringfy 和 parse 会有一些复杂性,但这是我使用 Regex 的唯一方法:

    var arr = ["some", "", "", "value", "", "", ""];
    var result = JSON.parse(JSON.stringify(arr).replace(/(,"")+]$/,"]"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      • 2016-10-10
      相关资源
      最近更新 更多