我有一个字符串数组。有些元素是空的,即''
(没有null
,undefined
或仅包含空格字符的字符串。我需要删除这些空元素,但只能从数组的(右)端删除。应保留非空元素之前的空元素。如果数组中只有空字符串,则应返回空数组。
以下是我到目前为止的代码。它有效,但我想知道 - 有没有一种方法不需要所有这些if
?我可以不创建数组的内存副本吗?
function removeFromEnd(arr) {
t = [...arr].reverse().findIndex(e => e !== '');
if (t === 0) {
return arr;
} else if (t === -1) {
return [];
} else {
return arr.slice(0, -1 * t);
}
}
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));
[ 'a', 'b', '', 'c' ]
[ 'a' ]
[ '', '', '', '', 'c' ]
[]
答案 0 :(得分:4)
这是removeFromEnd
的尾递归实现。我们的实施:
reverse
find
或findIndex
Array.prototype.reduce
或Array.prototype.reduceRight
const identity = x =>
x
const Empty =
Symbol ()
const removeFromEnd = ([ x = Empty, ...xs ], cont = identity) =>
x === Empty
? cont ([])
: removeFromEnd (xs, end =>
end.length === 0 && x === ''
? cont ([])
: cont ([ x, ...end ]))
console.log (removeFromEnd ([ 'a', 'b', '', 'c', '', '' ]))
// [ 'a', 'b', '', 'c' ]
console.log (removeFromEnd ([ 'a', '', '' ]))
// [ 'a' ]
console.log (removeFromEnd ([ '', '', '', '', 'c' ]))
// [ '', '', '', '', 'c' ]
console.log (removeFromEnd ([ '', '', '', '' ]))
// []

我认为removeFromEnd
可以作为高阶函数进行改进,就像Array.prototype.filter
const identity = x =>
x
const Empty =
Symbol ()
const removeFromEnd = (f = Boolean, [ x = Empty, ...xs ], cont = identity) =>
x === Empty
? cont ([])
: removeFromEnd (f, xs, end =>
end.length === 0 && f (x)
? cont ([])
: cont ([ x, ...end ]))
console.log (removeFromEnd (x => x === '', [ 'a', 'b', '', 'c', '', '', false, 0 ]))
// [ 'a', 'b', '', 'c', '', '', false, 0 ]
console.log (removeFromEnd (x => !x, [ 'a', 'b', '', 'c', '', '', false, 0 ]))
// [ 'a', 'b', '', 'c' ]

对于初学者来说,removeFromEnd
表示没有幻想的ES6解构语法或箭头函数
const identity = function (x)
{
return x
}
const removeFromEnd = function (f = Boolean, xs = [], i = 0, cont = identity)
{
if (i > xs.length)
return cont ([])
else
return removeFromEnd (f, xs, i + 1, function (end) {
if (end.length === 0 && f (xs [i]))
return cont ([])
else
return cont ([ xs [i] ].concat (end))
})
}
const data =
[ 'a', 'b', '', 'c', '', '', false, 0 ]
console.log (removeFromEnd (x => x === '', data))
// [ 'a', 'b', '', 'c', '', '', false, 0 ]
console.log (removeFromEnd (x => !x, data))
// [ 'a', 'b', '', 'c' ]

上面使用的延续传递方式对您来说可能看起来很陌生,但如果您想要写removeFromEnd
,这是必不可少的:
恢复命令式样式,JavaScript允许我们编写没有持续复杂性的程序 - 但是,递归调用不再处于尾部位置
我分享了这个版本的程序,因为大多数对功能性思维不熟悉的人来自于编写这样的程序。看到以不同风格表达的同一个程序,总能帮助我。也许它可以用同样的方式帮助你^^
const removeFromEnd = function (f = Boolean, xs = [], i = 0)
{
if (i > xs.length)
return []
const end =
removeFromEnd (f, xs, i + 1)
if (end.length === 0 && f (xs [i]))
return []
return [ xs [i] ] .concat (end)
}
const data =
[ 'a', 'b', '', 'c', '', '', false, 0 ]
console.log (removeFromEnd (x => x === '', data))
// [ 'a', 'b', '', 'c', '', '', false, 0 ]
console.log (removeFromEnd (x => !x, data))
// [ 'a', 'b', '', 'c' ]

答案 1 :(得分:1)
我使用reduce并且只添加一个元素,如果它不是空字符串或者数组中已经有条目
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));
function removeFromEnd(arr) {
return arr.reduceRight((a, b) => {
if (b !== '' || a.length) a.push(b);
return a;
}, []).reverse();
}
答案 2 :(得分:1)
您可以使用reduceRight
执行此操作,并在找到非空字符串的第一个元素时更改一个值。
function removeFromEnd(arr) {
return arr.reduceRight((r, e) => {
if (e) r.match = true;
if (r.match) r.arr.unshift(e)
return r;
}, {arr: []}).arr
}
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));
答案 3 :(得分:1)
另一种方法是使用 reduceRight
功能以及 Spread syntax
。
let removeFromEnd = (arr) => arr.reduceRight((a, b) => ((b !== '' || a.length) ? [b, ...a] : a), []);
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));

.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 4 :(得分:0)
您可以反转数组并删除元素,直到找到非空字符串。
以下是一个例子:
function removeFromEnd(arr){
return arr.reverse().filter(function(v){
if(v !== ""){
this.stopRemoving = true;
}
return this.stopRemoving;
}, {stopRemoving: false}).reverse();
}
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));
以下是使用经典循环的示例
function removeFromEnd(arr){
for(var i = arr.length - 1; i >= 0; i--){
if(arr[i] !== ""){
break;
}
arr.pop();
}
return arr;
}
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));
答案 5 :(得分:0)
有没有一种方法不需要所有这些ifs?我可以不创建数组的内存副本吗?
可能不是很实用,但是非常直接的实现:
function removeFromEnd(arr) {
let i = arr.length - 1;
while (arr[i] === "") i--;
return arr.slice(0, i + 1);
}
console.log(removeFromEnd(['a', 'b', '', 'c', '', '']));
console.log(removeFromEnd(['a', '', '']));
console.log(removeFromEnd(['', '', '', '', 'c']));
console.log(removeFromEnd(['', '', '', '']));
这里很难找到平衡......你标记了functional-programming
,@ naomik的答案显示了一个漂亮的功能解决方案,它与报价中的标签和关注点相匹配。
如果您只是想简化和优化,我的片段可能就足够了......