在for循环中使用拼接从数组中删除项目[重复]

Posted

技术标签:

【中文标题】在for循环中使用拼接从数组中删除项目[重复]【英文标题】:Remove items from array with splice in for loop [duplicate] 【发布时间】:2013-04-19 12:00:06 【问题描述】:

我想实现一种 jQuery 实时搜索。 但是在将输入发送到服务器之前,我想删除我的数组中包含 3 个或更少字符的所有项目(因为在德语中,这些词通常可以在搜索方面被忽略) 所以["this", "is", "a", "test"]变成["this", "test"]

$(document).ready(function() 
var timer, searchInput;
$('#searchFAQ').keyup(function() 
    clearTimeout(timer);
    timer = setTimeout(function() 
        searchInput = $('#searchFAQ').val().match(/\w+/g);
        if(searchInput) 
            for (var elem in searchInput) 
                if (searchInput[elem].length < 4) 
                    //remove those entries
                    searchInput.splice(elem, 1);
                
            
            $('#output').text(searchInput);
            //ajax call here
        
    , 500);
);
);

现在我的问题是在我的 for 循环中并非所有项目都被删除。 例如,如果我输入“这是一个测试”“是”被删除,“a”将保留。 JSFIDDLE

我认为问题在于 for 循环,因为如果我使用拼接删除一个项目,数组的索引会发生变化,所以它会继续使用“错误”索引。

也许有人可以帮助我吗?

【问题讨论】:

我不明白为什么这不应该在服务器端完成。请记住,用户总是有可能关闭 javascript @Blazemonger 你是对的,但两种方式都应该是可能的。服务器端和客户端。 在客户端做这件事有什么好处呢?在上传搜索字符串之前,您只删除了大约十几个字符,并且无论如何您都将重复检查服务器端。仅当您想在提交之前向用户返回错误时,这才值得。 好吧,我也想过这个问题,但可以说这对我来说更像是一种锻炼。事实上,让服务器完成工作更聪明,但我开始这样做并想要一个可行的解决方案;) 【参考方案1】:

解决方案 1

您可以向后循环,如下所示:

var searchInput, i;

searchInput = ["this", "is", "a", "test"];
i = searchInput.length;
while (i--) 
    if (searchInput[i].length < 4) 
        searchInput.splice(i, 1);
    

演示: http://jsfiddle.net/KXMeR/

这是因为在数组中进行增量迭代,当你拼接它时,数组被原地修改,所以项目被“移位”并且你最终跳过了一些迭代。向后循环(使用while 甚至for 循环)可以解决此问题,因为您没有在拼接方向上循环。


解决方案 2

同时,生成一个新数组通常比就地修改一个数组更快。这是一个例子:

var searchInput, newSearchInput, i, j, cur;

searchInput = ["this", "is", "a", "test"];
newSearchInput = [];
for (i = 0, j = searchInput.length; i < j; i++) 
    cur = searchInput[i];
    if (cur.length > 3) 
        newSearchInput.push(cur);
    

其中newSearchInput 将只包含有效长度的项目,而您仍然拥有searchInput 中的原始项目。

演示: http://jsfiddle.net/RYAx2/


解决方案 3

除了上面的第二种解决方案之外,还有一个类似的、更新的Array.prototype 方法可以更好地处理这个问题:filter。这是一个例子:

var searchInput, newSearchInput;

searchInput = ["this", "is", "a", "test"];
newSearchInput = searchInput.filter(function (value, index, array) 
    return (value.length > 3);
);

演示: http://jsfiddle.net/qky7D/


参考资料:

Array.prototype.filter - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter Array.prototype.filter 浏览器支持 - http://kangax.github.io/es5-compat-table/#Array.prototype.filter

【讨论】:

谢谢你这样做了。有时你只是完全智障,你的大脑会阻止所有聪明的思考方式:D我会尽快接受这个答案;) @SirDerpington 哈哈,没问题,谢谢 :) 是的,这完全取决于您的实施。我更喜欢第一个示例,除非您需要引用原始数组,即使 splice 慢一点(除非此代码在一个巨大的数组上快速运行几次,否则您不会看到速度差异)。 looping in the direction you're splicing 惊人的概念。 我会说你拯救了我的一天,但我已经浪费了一天的时间来弄清楚我的代码为什么不起作用:D 带有正确解释的精确解决方案。非常感谢。【参考方案2】:
var myArr = [0,1,2,3,4,5,6];

问题陈述:

myArr.splice(2,1);

  \\ [0, 1, 3, 4, 5, 6];

现在在第二个位置移动 3 次,长度减少 1,这会产生问题。

解决方案:一个简单的解决方案是在拼接时反向迭代。

var i = myArr.length;
while (i--) 
    // do your stuff

【讨论】:

【参考方案3】:

如果您安装了 lodash 库,那么您可能需要考虑使用它们。

函数是_.forEachRight (从右到左迭代集合的元素)

这是一个例子。

var searchInput = ["this", "is", "a", "test"];

_.forEachRight(searchInput, function(value, key) 

    if (value.length < 4) 
        searchInput.splice(key, 1);
    
);

【讨论】:

非常好..真的很有帮助..谢谢【参考方案4】:

您还可以使用$.grep 函数来过滤数组:

var timer, searchInput;
$('#searchFAQ').keyup(function () 
    clearTimeout(timer);
    timer = setTimeout(function () 
        searchInput = $('#searchFAQ').val().split(/\s+/g); // match is okay too
        searchInput = $.grep(searchInput, function(el) 
            return el.length >= 4;
        );
        console.log(searchInput);
    , 500);
);

http://jsfiddle.net/dfsq/4Wdp9/

【讨论】:

【参考方案5】:

另一种方法是在从数组 (x--) 切片时减少索引,这样当数组向下移动时,不会跳过下一个元素。

var searchInput;

searchInput = ["this", "is", "a", "test"];
for (var x = 0; x < searchInput.length; x++) 
    if (searchInput[x].length < 4) 
        searchInput.splice(x--, 1);
    


console.log(searchInput);

演示: https://jsfiddle.net/alinaeem229/n2kq3690/1/

【讨论】:

以上是关于在for循环中使用拼接从数组中删除项目[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从数组中删除重复项时出现超出范围异常

增强的 For 循环异常 [重复]

从Ruby中的数组中删除重复元素

使用函数从数组中删除项目

在 vue.js 中推送和拼接不更新或删除

Vuejs - 如何使用 v-for 获取数组中的所有唯一值(删除重复项)