简体   繁体   English

如何根据对对象的了解,从数组中查找和删除对象?

[英]How do I find and remove an object from an array based on what I know about the contents of that object?

For the following: 对于以下内容:

var arr = [{ "packageId": "11", "machineId": "1", "operationType": "Download" }, { "packageId": "12", "machineId": "1", "operationType": "Download" }, { "packageId": "14", "machineId": "1", "operationType": "Download" }];
var index = arr.indexOf({ "packageId": "12", "machineId": "1", "operationType": "Download" });
console.log("index: " + index);
arr.splice(index, 1);

I always get -1 as a result. 结果我总是得到-1 Why is that? 这是为什么?

I need to be able to remove an object from an array. 我需要能够从数组中删除一个对象。

[Note in reference to the original wording of your question: There is no JSON in your question actually; [请注意问题的原始措辞:实际上,您的问题中没有JSON; JSON refers to object notation. JSON是指对象符号。 What you have inside your array and your indexOf() call are object literals, represented by {} with optional properties inside.] 数组和indexOf()调用中包含的是对象文字,由{}表示,内部带有可选属性。]

COMPARING OBJECTS 比较对象

The problem is that the object literal you create inside your indexOf() call is a new object unto itself and therefore not equal to anything inside the array arr . 问题在于您在indexOf()调用中创建的对象文字本身就是一个新对象,因此不等于数组arr任何内容。 Instead, you have to loop through all the properties in each object and check their equivalence. 相反,您必须遍历每个对象中的所有属性并检查它们的等效性。 I wrote this function quickly now and you can test it in the JSFiddle link at the bottom of this answer. 我现在快速编写了此函数,您可以在此答案底部的JSFiddle链接中对其进行测试。

function compareObjs(obj1, obj2) {
    var k,
        rtn = true; // assume objects are similar, and then attempts to falsify
    for (k in obj1) {
        if (obj1.hasOwnProperty(k) && obj2.hasOwnProperty(k)) { // check property belongs to both obj1 and obj2
            if (typeof obj1[k] === 'Object') {
                compareObjs(obj1, obj2); // recursive call, to compare two objects within the object
            } else {
                rtn = (obj1[k] === obj2[k]) ? rtn : false; // check value of property is equivalent; if not set the return value to false
            }
        } else {
            rtn = false;
        }
    }
}

You feed it two objects, so in your question that would be: 您向它提供了两个对象,因此在您的问题中将是:

compareObjs(arr[1], { "packageId": "12", "machineId": "1", "operationType": "Download" });

This should return true. 这应该返回true。 If the two objects aren't equivalent then it will return false. 如果两个对象不相等,则它将返回false。

FINDING AN ARRAY ELEMENT 查找数组元素

I'm guessing you would want to use this to check the position of a particular package in the array, in which case you would probably need to loop through your array checking each object in it for equivalence, like so: 我猜想您将要使用它来检查特定包在数组中的位置,在这种情况下,您可能需要遍历数组,检查其中的每个对象是否相等,如下所示:

var i = 0, // Declare the variables upfront
    l = arr.length, // including the length of the array
    r = -1;  // and where you want your result, which will automatically be -1 until a match is found.
for (i; i < l; i += 1) {
    r = (compareObjs(arr[i], { "packageId": "12", "machineId": "1", "operationType": "Download" }) && r === -1) ? i : r;
}

Here r should give you the first position in which an equivalent object is found. 在这里r应该给您找到等同对象的第一个位置。

REMOVING THE RELEVANT ARRAY ELEMENT 删除相关的数组元素

You can then remove the object from the array with reference to r , using the splice() method like so: 然后可以使用splice()方法,参照r ,从数组中删除对象,如下所示:

arr.splice(r, 1);

You might want to drop this code into a function too but I don't know the structure of the rest of your programme so will leave you to ponder that! 您可能也希望将此代码放入函数中,但是我不知道程序其余部分的结构,因此请您仔细考虑!

JSFiddle here . JSFiddle在这里 (You will need to open the browser console to view the results.) (您将需要打开浏览器控制台以查看结果。)

The {} object literal you are creating is actually a different object than the object in arr , so they cannot be compared directly and indexOf will fail. 您正在创建的{}对象文字实际上是与arr的对象不同的对象,因此无法直接比较它们,并且indexOf将失败。 You have to use good old fashioned iteration: 您必须使用良好的老式迭代:

arr.filter(function (elem) {
    return elem.packageId != 12
        || elem.machineId != 1
        || elem.operationType != 'Download';
});

You can of course also compare to an object if you need. 当然,如果需要,您也可以与对象进行比较。

var compareTo = {'packageId': '12'};
arr.filter(function (elem) {
    var matches = 0, elements = 0;
    for (var x in compareTo) {
        elements++;
        if (compareTo.hasOwnProperty(x) && elem.hasOwnProperty(x)
            && elem (x) == compareTo(x)
        ) {
            matches++;
        }
    }
    return matches == elements;
});

I suggest you another possible solution. 我建议您另一种可能的解决方案。

If you can modify your data structure, use an Object in order to store your data, an shape it as an associative array: 如果可以修改数据结构,请使用一个Object来存储数据,并将其成形为关联数组:

var assocArr = new Object();
assocArr["11"] = {"packageId": "11", "machineId": "1", "operationType": "Download"};
assocArr["12"] = { "packageId": "12", "machineId": "1", "operationType": "Download" };
assocArr["14"] = { "packageId": "14", "machineId": "1", "operationType": "Download" };

delete assocArr["11"];

Advantages: 好处:

  • direct data access 直接数据访问
  • trivial insert and deletion 琐碎的插入和删除

You could also arrange a class to manage your data: 您还可以安排一个班来管理数据:

var AssocArray = function(){
  var collection = new Object();

  this.add = function(id, o){
    collection[id] = o;
  }

  this.remove = function(id){
    delete collection[id];
  }

  this.getById = function(id){
    return collection[id];
  }

  this.get = function(){
    return collection;
  }
}

var myAssoc = new AssocArray();
myAssoc.add("11",{"packageId": "11", "machineId": "1", "operationType": "Download"});
myAssoc.add("12",{ "packageId": "12", "machineId": "1", "operationType": "Download"});
myAssoc.add("14",{ "packageId": "14", "machineId": "1", "operationType": "Download"});

if(myAssoc.getById("10")) myAssoc.remove("10");
if(myAssoc.getById("14")) myAssoc.remove("14");

console.log(myAssoc.get());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM