如何根据数组内容添加/删除数组中的元素

时间:2015-03-01 19:34:22

标签: javascript arrays angularjs

我已经在这篇文章中苦苦挣扎了好几天,我似乎无法找到错误。我有一个包含几个对象的数组:

myMainPostObj.categories = [Object, Object]

这是为帖子添加/删除类别。想象一下,我正在编辑已经与几个类别相关联的现有帖子(根据上面的代码)。

我还有一个数组,其中包含db中的所有类别(包括与帖子关联的类别)。在我的js控制器上,我有以下代码:

$scope.addCategory = function (cat) {
    for (var i in $scope.post.category_ids) {
        if (cat._id === $scope.post.category_ids[i]) {
            $scope.post.category_ids.slice(i, 1);
        } else if (cat._id !== $scope.post.category_ids[i]) {
            $scope.post.category_ids.push(cat._id);
        }
    }
}

每次用户点击某个类别时,都会调用上述功能。我们的想法是让上面的函数循环遍历帖子中的类别(与帖子相关联),并将其与作为参数传递的类别进行比较。如果匹配该功能应删除该类别。如果它不应该添加。

理论上这看起来很直接,但无论出于何种原因,如果我勾选与帖子无关的类别,它会向数组添加两个(不是预期的)类别。当我尝试移除时也会发生同样的情况。

这是Angular控制器的一部分,可以找到整个代码here

3 个答案:

答案 0 :(得分:0)

我想问题可能是你在使用for循环迭代它时改变了category_ids数组。你可能最好尝试这样的事情:

$scope.addCategory = function (cat) {
var catIndex = $scope.post.category_ids.indexOf(cat._id);
if (catIndex > -1)
    $scope.post.category_ids.splice(catIndex, 1);
else
    $scope.post.category_ids.push(cat._id);
}

请注意,IE7-8似乎不支持indexOf。

答案 1 :(得分:0)

让我们简化一下:

const CATEGORIES = [1, 2, 3];

let addCategory = (postCategories, categoryId) => {
  CATEGORIES.forEach((cId, index) => {
    if (postCategories[index] === cId) console.log("Removing", categoryId);
    else console.log("Adding", categoryId);
  });
  return postCategories;
};

请忽略我们实际上没有改变传入的数组的事实。

A等于或等于B - 没有第三个选项(FILE_NOT_FOUND除外)。因此,您循环遍历所有类别,并且每次在当前索引的数组中找不到类别ID时,都会将其添加到postCategories数组

问题的正确解决方法就是使用Set(或者如果您需要的不仅仅是前沿的ES6支持,那么这个对象没有原型):

// Nicer, ES6-or-pollyfill option
var postCategories = new Set();
postCategories.add(categoryId);

// Or, in the no-prototype option:
var postCategories = Object.create(null);
postCategories[categoryId] = true;
// Then serialization needs an extra step if you need an array:
parentObject.postCategories = Object.keys(parentObject.postCategories);

答案 2 :(得分:0)

代码中的错误是,对于循环的每次迭代,您要么删除或添加类别。这不对......如果当前的id匹配,你应该删除,但只有在根本没有匹配时才添加。像这样:

$scope.addCategory = function (cat) {
    var found = false;
    for (var i in $scope.post.category_ids) {
        if (cat._id === $scope.post.category_ids[i]) {
            $scope.post.category_ids.splice(i, 1);   // splice, not slice
            found = true;
        } 
    }
    if (!found)  // add only if it wasn't found
        $scope.post.category_ids.push(cat._id);
}