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

How to add/remove elements from array based on array contents

本文关键字:数组 删除 元素 何根 添加      更新时间:2023-09-26

我已经为这篇文章挣扎了几天,似乎找不到哪里出了问题。我有一个数组,里面有几个对象:

myMainPostObj.categories = [Object, Object]

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

我还有一个数组,它包含数据库中的所有类别(包括与帖子相关联的类别)。在我的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控制器的一部分,整个代码可以在这里找到

代码中的错误是,对于循环的每次迭代,您要么删除要么添加一个类别。这不对。。。如果当前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);
}

我想问题可能是您在使用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。

让我们稍微简化一下:

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);