简体   繁体   English

如何从 JavaScript 关联数组中删除对象?

[英]How do I remove objects from a JavaScript associative array?

Suppose I have this code:假设我有这个代码:

var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

Now if I wanted to remove "lastname"?....is there some equivalent of myArray["lastname"].remove() ?现在,如果我想删除“姓氏”?....是否有一些等效的myArray["lastname"].remove()

(I need the element gone because the number of elements is important and I want to keep things clean.) (我需要元素消失,因为元素的数量很重要,我想保持干净。)

Objects in JavaScript can be thought of as associative arrays, mapping keys (properties) to values. JavaScript 中的对象可以被认为是关联数组,将键(属性)映射到值。

To remove a property from an object in JavaScript you use the delete operator:要从 JavaScript 中的对象中删除属性,请使用delete运算符:

const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false

Note that when delete is applied to an index property of an Array , you will create a sparsely populated array (ie. an array with a missing index).请注意,当delete应用于Array的 index 属性时,您将创建一个稀疏填充的数组(即缺少索引的数组)。

When working with instances of Array , if you do not want to create a sparsely populated array - and you usually don't - then you should use Array#splice or Array#pop .在使用Array实例时,如果您不想创建一个稀疏填充的数组 - 而您通常不想 - 那么您应该使用Array#spliceArray#pop

Note that the delete operator in JavaScript does not directly free memory.请注意,JavaScript 中的delete运算符不会直接释放内存。 Its purpose is to remove properties from objects.它的目的是从对象中删除属性。 Of course, if a property being deleted holds the only remaining reference to an object o , then o will subsequently be garbage collected in the normal way.当然,如果被删除的属性持有对象o的唯一剩余引用,那么o将随后以正常方式被垃圾收集。

Using the delete operator can affect JavaScript engines' ability to optimise code .使用delete操作符会影响 JavaScript 引擎优化代码的能力。

All objects in JavaScript are implemented as hashtables/associative arrays. JavaScript 中的所有对象都实现为哈希表/关联数组。 So, the following are the equivalent:因此,以下是等效的:

alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);

And, as already indicated, you "remove" a property from an object via the delete keyword, which you can use in two ways:而且,如前所述,您可以通过delete关键字从对象中“删除”一个属性,您可以通过两种方式使用它:

delete myObj["SomeProperty"];
delete myObj.SomeProperty;

Hope the extra info helps...希望额外的信息有帮助...

None of the previous answers address the fact that JavaScript does not have associative arrays to begin with - there is no array type as such, see typeof .之前的答案都没有解决 JavaScript 没有关联数组开始的事实 - 没有array类型,请参阅typeof

What JavaScript has, are object instances with dynamic properties. JavaScript 拥有的是具有动态属性的对象实例。 When properties are confused with elements of an Array object instance then Bad Things™ are bound to happen:当属性与 Array 对象实例的元素混淆时,Bad Things™ 必然会发生:

Problem问题

var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log("number of elements: ", elements.length)   // Returns 2
delete elements[1]
console.log("number of elements: ", elements.length)   // Returns 2 (?!)

for (var i = 0; i < elements.length; i++)
{
   // Uh-oh... throws a TypeError when i == 1
   elements[i].onmouseover = function () { window.alert("Over It.")}
   console.log("success at index: ", i)
}

Solution解决方案

To have a universal removal function that does not blow up on you, use:要拥有不会对您造成影响的通用删除功能,请使用:

Object.prototype.removeItem = function (key) {
   if (!this.hasOwnProperty(key))
      return
   if (isNaN(parseInt(key)) || !(this instanceof Array))
      delete this[key]
   else
      this.splice(key, 1)
};

//
// Code sample.
//
var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log(elements.length)                        // Returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.log(elements.hasOwnProperty("prop"))        // Returns false as it should
console.log(elements.length)                        // returns 1 as it should

That only deletes the object, but it still keeps the array length the same.这只会删除对象,但它仍然保持数组长度不变。

To remove the element from the array, you need to do something like:要从数组中删除元素,您需要执行以下操作:

array.splice(index, 1);

While the accepted answer is correct, it is missing the explanation why it works.虽然接受的答案是正确的,但它没有解释它为什么起作用。

First of all, your code should reflect the fact that this is not an array:首先,您的代码应该反映这不是数组的事实:

var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;

Note that all objects (including Array s) can be used this way.请注意,所有对象(包括Array )都可以这样使用。 However, do not expect for standard JavaScript array functions (pop, push, etc.) to work on objects!但是,不要指望标准的 JavaScript 数组函数(pop、push 等)可以处理对象!

As said in accepted answer, you can then use delete to remove the entries from objects:正如在接受的答案中所说,您可以使用delete从对象中删除条目:

delete myObject["lastname"]

You should decide which route you wish to take - either use objects (associative arrays / dictionaries) or use arrays (maps).你应该决定你想走哪条路——要么使用对象(关联数组/字典),要么使用数组(地图)。 Never mix the two of them.切勿将两者混用。

There is an elegant way in the Airbnb Style Guide to do this (ECMAScript 7): Airbnb 风格指南中有一种优雅的方式来做到这一点(ECMAScript 7):

const myObject = {
  a: 1,
  b: 2,
  c: 3
};
const { a, ...noA } = myObject;
console.log(noA); // => { b: 2, c: 3 }

Copyright: https://codeburst.io/use-es2015-object-rest-operator-to-omit-properties-38a3ecffe90版权所有: https : //codeburst.io/use-es2015-object-rest-operator-to-omit-properties-38a3ecffe90

As other answers have noted, you are not using a JavaScript array, but a JavaScript object, which works almost like an associative array in other languages except that all keys are converted to strings.正如其他答案所指出的,您使用的不是 JavaScript 数组,而是 JavaScript 对象,它的工作方式几乎与其他语言中的关联数组类似,只是所有键都转换为字符串。 The new Map stores keys as their original type.Map将键存储为其原始类型。

If you had an array and not an object, you could use the array's .filter function, to return a new array without the item you want removed:如果你有一个数组而不是一个对象,你可以使用数组的.filter函数,返回一个没有你想要删除的项目的新数组:

var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
    return item !== 'Smith';
});

If you have an older browser and jQuery, jQuery has a $.grep method that works similarly:如果您有旧浏览器和 jQuery,jQuery 有一个$.grep方法,其工作方式类似:

myArray = $.grep(myArray, function(item) {
    return item !== 'Smith';
});

Use method splice to completely remove an item from an object array:使用方法splice从对象数组中完全删除一个项目:

Object.prototype.removeItem = function (key, value) {
    if (value == undefined)
        return;

    for (var i in this) {
        if (this[i][key] == value) {
            this.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");

You are using Object, and you don't have an associative array to begin with.您正在使用 Object,并且您没有开始的关联数组。 With an associative array, adding and removing items goes like this:使用关联数组,添加和删除项目是这样的:

    Array.prototype.contains = function(obj)
    {
        var i = this.length;
        while (i--)
        {
            if (this[i] === obj)
            {
                return true;
            }
        }
        return false;
    }


    Array.prototype.add = function(key, value)
    {
        if(this.contains(key))
            this[key] = value;
        else
        {
            this.push(key);
            this[key] = value;
        }
    }


    Array.prototype.remove = function(key)
    {
        for(var i = 0; i < this.length; ++i)
        {
            if(this[i] == key)
            {
                this.splice(i, 1);
                return;
            }
        }
    }



    // Read a page's GET URL variables and return them as an associative array.
    function getUrlVars()
    {
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }

        return vars;
    }


    function ForwardAndHideVariables() {
        var dictParameters = getUrlVars();

        dictParameters.add("mno", "pqr");
        dictParameters.add("mno", "stfu");

        dictParameters.remove("mno");


        for(var i = 0; i < dictParameters.length; i++)
        {
            var key = dictParameters[i];
            var value = dictParameters[key];
            alert(key + "=" + value);
        }
        // And now forward with HTTP-POST
        aa_post_to_url("Default.aspx", dictParameters);
    }


    function aa_post_to_url(path, params, method) {
        method = method || "post";

        var form = document.createElement("form");

        // Move the submit function to another variable
        // so that it doesn't get written over if a parameter name is 'submit'
        form._submit_function_ = form.submit;

        form.setAttribute("method", method);
        form.setAttribute("action", path);

        for(var i = 0; i < params.length; i++)
        {
            var key = params[i];

            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }

        document.body.appendChild(form);
        form._submit_function_(); // Call the renamed function
    }

You can remove an entry from your map by explicitly assigning it to 'undefined'.您可以通过将条目显式分配给“未定义”来从地图中删除条目。 As in your case:就像你的情况:

myArray["lastname"] = undefined; myArray[“姓氏”] = 未定义;

If, for whatever reason, the delete key is not working (like it wasn't working for me), you can splice it out and then filter the undefined values:如果出于某种原因,删除键不起作用(就像它对我不起作用),您可以将其拼接起来,然后过滤未定义的值:

// To cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});

Don't try and chain them since splice returns removed elements;不要尝试链接它们,因为 splice 返回已删除的元素;

如果您的项目中有Underscore.js依赖项,这将非常简单 -

_.omit(myArray, "lastname")

We can use it as a function too.我们也可以将其用作函数。 Angular throws some error if used as a prototype.如果用作原型,Angular 会抛出一些错误。 Thanks @HarpyWar.谢谢@HarpyWar。 It helped me solve a problem.它帮助我解决了一个问题。

var removeItem = function (object, key, value) {
    if (value == undefined)
        return;

    for (var i in object) {
        if (object[i][key] == value) {
            object.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

removeItem(collection, "id", "87353080-8f49-46b9-9281-162a41ddb8df");

By using the "delete" keyword, it will delete the array element from array in JavaScript.通过使用"delete"关键字,它将从 JavaScript 中的数组中删除数组元素。

For example,例如,

Consider following statements.考虑以下语句。

var arrayElementToDelete = new Object();

arrayElementToDelete["id"]           = "XERTYB00G1";
arrayElementToDelete["first_name"]   = "Employee_one";
arrayElementToDelete["status"]       = "Active";

delete arrayElementToDelete["status"];

The last line of the code will remove the array element whose key is "status" from the array.代码的最后一行将从数组中删除键为“status”的数组元素。

var myArray = newmyArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

var s = JSON.stringify(myArray);

s.replace(/"lastname[^,}]+,/g, '');
newmyArray = JSON.parse(p);

Without looping/iterates we get the same result.没有循环/迭代我们得到相同的结果。

For "Arrays":对于“数组”:

If you know the index:如果您知道索引:

array.splice(index, 1);

If you know the value:如果你知道这个值:

function removeItem(array, value) {
    var index = array.indexOf(value);
    if (index > -1) {
        array.splice(index, 1);
    }
    return array;
}

The most upvoted answer for delete works well in case of objects but not for the real arrays.最受好评的delete答案适用于对象,但不适用于实际数组。 If I use delete it removes elements from loops but keeps the element as empty and length of array wont change.如果我使用delete它会从循环中删除元素,但将元素保持为empty并且数组的长度不会改变。 This may be a problem in some scenarios.在某些情况下,这可能是一个问题。

For example, if I do myArray.toString() on myArray after removal via delete , it creates an empty entry, ie ,, .例如,如果我在通过delete后对 myArray 执行 myArray.toString() ,它会创建一个空条目,即,,

The only working method for me:对我来说唯一的工作方法:

function removeItem (array, value) {
    var i = 0;
    while (i < array.length) {
        if(array[i] === value) {
            array.splice(i, 1);
        } else {
            ++i;
        }
    }
    return array;
}

Usage:用法:

var new = removeItem( ["apple","banana", "orange"],  "apple");
// ---> ["banana", "orange"]

You can do the following if you want a more functional and elegant approach:如果您想要更实用和更优雅的方法,您可以执行以下操作:

const o = { firstName: "foo", lastName: "bar" };
const { lastName, ...removed } = o;
lastName // bar
removed // { firstName: "foo" }

Not that the value of removed will be undefined if there are no items left in the object.并不是说如果对象中没有剩余项目,则removed的值将是未定义的。

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

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