Як видалити об'єкти з асоціативного масиву javascript?


619

Припустимо, у мене є цей код:

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

Тепер, якщо я хотів видалити "прізвище"? .... Чи є якийсь еквівалент
myArray["lastname"].remove()?

(Мені потрібен елемент, який пропав, тому що важлива кількість елементів, і я хочу підтримувати чистоту.)


27
Порада: не плутайте масиви та карти. Деякі мови, як-от php, мають один об'єкт для обох. Хоча ви тут використовували правильний тип (новий Object ()), ви назвали його myArray, це лише питання стандартів для багажу.
— Хуан Мендес

Не забувайте, що JavaScript не вводить текст і все є об'єктом. Дивіться відповідь Саула нижче.
— stevek

4
@StephanKristyn - якщо бути точним, JS має типи, але динамічно і слабко . Наприклад, хоча його змінні справді є нетиповими, їх значення не є. Це динамічна частина. Слабкий означає, що операції між різними типами значень не є чітко визначеними і покладаються на закулісні перетворення; наприклад "Test" + {};, ідеально правильне твердження JS.
— Саул

Відповіді:


1135

Об'єкти в JavaScript можна розглядати як асоціативні масиви, відображення ключів (властивостей) до значень.

Щоб видалити властивість з об’єкта в JavaScript, ви використовуєте deleteоператор:

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

Зауважте, що при deleteзастосуванні до властивості індексу Array, ви створите малонаселений масив (тобто масив із відсутнім індексом).

Якщо ви працюєте з екземплярами Array, якщо ви не хочете створювати малонаселений масив - а зазвичай цього не робите, - слід використовувати Array#spliceабо Array#pop.

Зауважте, що deleteоператор у JavaScript не вільно звільняє пам'ять. Його мета - видалення властивостей з об’єктів. Звичайно, якщо видалений ресурс містить єдине посилання на об'єкт o, то oзгодом сміття збирається звичайним чином.

Використання deleteоператора може вплинути на можливість двигунів JavaScript оптимізувати код .


18
Це спричинить проблеми при використанні в екземплярі об'єкта Array для видалення наявного елемента, наприклад delete myArray[0]. Дивіться stackoverflow.com/a/9973592/426379 та Видалення елементів масиву
— Saul

4
Які проблеми будуть викликані?
— Gottox

26
@Gottox - lengthВластивість об'єкта Array залишається незмінною.
— Саул

12
@Saul: виникли б проблеми, якби myArrayнасправді використовувався як масив - але це не так ( myArrayце прикрою назвою), це об’єкт. Так що в цьому випадку deleteвсе в порядку. Зауважте, що навіть якщо він був створений як new Array()і використовується як асоціативний масив, все одно буде нормально. Ваше попередження все-таки має бути про що слід пам’ятати, якщо ви використовуєте реальні масиви, хоча.
— johndodo

2
@johndodo - Правда. Ось чому я почав свій початковий коментар з Це спричинить проблеми при використанні в екземплярі об'єкта Array . Я все ж віддаю перевагу підходу, який працює у всіх випадках правильно, дивіться мою відповідь нижче.
— Саул

79

Усі об'єкти в JavaScript реалізовані у вигляді хештелів / асоціативних масивів. Отже, такі еквіваленти:

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

І, як уже було зазначено, ви "видаляєте" властивість з об'єкта за допомогою deleteключового слова, яке ви можете використовувати двома способами:

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

Сподіваюся, додаткова інформація допомагає ...


10
слід зазначити, що позначення крапки не працює, якщо властивість не є простим терміном. тобто myObj['some;property']працює, але myObj.some;propertyне буде (з очевидних причин). Також може бути не очевидно, що ви можете використовувати змінну в позначеннях дужок, тобтоvar x = 'SomeProperty'; alert(myObj[x])
— Kip

2
"Усі об'єкти в JavaScript реалізовані як хештелі / асоціативні масиви." - помилково. V8 вважає за краще зберігати об’єкт як прихований клас + щільно упаковані поля. Тільки якщо ви робите для них дивні речі (наприклад, видалення полів), він відмовляється і використовує хеш-карту за кадром.
— Джон Дворак

4
@JanDvorak - ага, ти визнаєш, коли ця відповідь була написана спочатку, так? Цей опис був і все ще є достатнім для більшості цілей. Це сказало, що я розумію, як нудно педантично. :)
— Джейсон Бантінг

41

Жодна з попередніх відповідей не стосується того факту, що у Javascript немає асоціативних масивів для початку - немає такого arrayтипу, див typeof.

Javascript - це об'єкти з динамічними властивостями. Якщо властивості плутати з елементами екземпляра об'єкта Array, тоді Bad Things ™ обов'язково відбудеться:

Проблема

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

Рішення

Щоб мати універсальну функцію видалення, яка не підіймається на вас, використовуйте:

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

8
У цього рішення є два питання: він приховує той факт, що масиви та об’єкти - це зовсім різні звірі в JS (ви це знаєте, але, очевидно, що ОП це не так), і він використовує прототипи. ОП було б краще, якби він дізнався про масиви та об’єкти (і назвав би його змінні відповідно) - спроба приховати відмінності між двома лише доставить йому більше проблем. ІМХО, звичайно.
— johndodo

1
@johndodo - всі Arrays в JS є об'єктами, спробуйте typeof new Array();або typeof []перевірити. Arrayпросто певний вид предмета і зовсім не "інший звір". У JS об'єкти розрізняють за назвою конструктора та ланцюжком прототипу, див . Програмування на основі прототипів .
— Саул

9
Ви пропускаєте суть. Я знаю, що масиви теж є об'єктами, але це не означає, що їх розумно використовувати як такі. Програміст повинен вирішити, чи хоче він використовувати щось як масив (з push, pop, [], ...) або як об'єкт / "асоціативний масив". Мікс і сірник - не гарний рецепт, саме через проблеми, які ваше рішення намагається приховати. Якщо ви заздалегідь вирішите, який шаблон дизайну використовувати (масив чи об’єкт), таких проблем не виникне.
— johndodo

7
@johndodo - Про які конкретно проблеми ти говориш? Метою вищевказаного коду є вирішення проблеми, пов'язаної з deleteоператором дефіциту, Arrayшляхом надання простої поліморфної функції.
— Саул

1
deleteне має дефіциту. deleteпризначений для видалення властивостей. Це воно. Застосування оператора видалення до індексу масиву видаляє цей індекс. Що ще потрібно для цього? Вам залишається розріджений масив, який є особливістю мови. Якщо ви не хочете розрідженого масиву, не видаляйте індекс: використовуйте spliceабо pop.
— Бен Астон

35

Це видаляє лише видалення об'єкта, але все ж зберігає довжину масиву однаковою.

Щоб видалити, потрібно зробити щось на кшталт:

array.splice(index, 1);

11
Дійсно, але в цьому випадку масив не використовується, а лише звичайний старий об'єкт, таким чином він не має методу довжини чи сплайсингу.
— MooGoo

2
@Andreaa Panagiotidis За винятком випадків, коли ми не говоримо про масиви, і в цьому випадку це неправильно 100% часу 🙂
— Дренай

17

Хоча прийнята відповідь правильна, у неї відсутнє пояснення, чому це працює.

Перш за все, ваш код повинен відображати той факт, що це НЕ масив:

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

Зауважте, що всі об'єкти (включаючи їх Array) можна використовувати таким чином. Однак не очікуйте, що стандартні функції масиву JS (pop, push, ...) працюватимуть на об'єктах!

Як сказано в прийнятій відповіді, ви можете використовувати deleteдля видалення записів з об'єктів:

delete myObject["lastname"]

Ви повинні вирішити, яким маршрутом ви хочете скористатися - або використовувати об'єкти (асоціативні масиви / словники), або використовувати масиви (карти). Ніколи їх не змішуйте.


6
Дуже гарна відповідь. Я лише радив би тому, хто читає це, що масиви в JavaScript не повинні абстрагуватися як "карти", а "списки". Це тому, що вам не слід намагатися контролювати індекс елементів при використанні масивів. Якщо ви спробуєте це ... ну, просто не робіть: D
— rodolfo42

6

Використовуйте метод 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");

1
це більш загальне рішення, його можна додати у файл js, і метод буде доступний для всіх масивів, а не лише для одного масиву.
— Хуссей

6

Як зазначалося в інших відповідях, те, що ви використовуєте, - це не масив Javascript, а об’єкт Javascript, який працює майже як асоціативний масив іншими мовами, за винятком того, що всі клавіші перетворені на рядки. Нова карта зберігає ключі як їх оригінальний тип.

Якщо у вас був масив, а не об’єкт, ви можете використовувати масив функцією .filter , щоб повернути новий масив без потрібного елемента, який вилучите :

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

Якщо у вас старший браузер і jQuery, jQuery має $.grepметод, який працює аналогічно:

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

ідеальне пояснення. Я використовував фільтр для досягнення бажаного результату. Поясніть, як працює елемент повернення для видалення об'єкта з масиву. Я припускаю, що він повертає масив до тих пір, поки він не включає рядок, який ви включили.
— Едвард


5

Ви використовуєте Object, у вас немає асоціативного масиву для початку. З асоціативним масивом додавання та видалення елементів відбувається так:

    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
    }

4

Ви можете видалити запис зі своєї карти, чітко призначивши її "невизначеною". Як у вашому випадку:

myArray ["прізвище"] = невизначено;


Це може бути корисно у випадках, коли не впевнені, чи існує ключ у словнику, але хочуть його переосмислити на випадок. Виправте мене, якщо я помиляюся Амітіс.
— Хассан Байг

3

Якщо з будь-якої причини ключ видалення не працює (як би він не працював для мене)

Ви можете їх сплайсувати, а потім відфільтрувати невизначені значення

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

Не намагайтеся зв'язати їх з ланцюгом, оскільки сплайс повертає видалені елементи;


3

Ми можемо використовувати його і як функцію. Кутовий кидає деяку помилку, якщо використовується як прототип. Дякую @HarpyWar. Це допомогло мені вирішити проблему.

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


1

Використовуючи "delete"ключове слово, він видалить елемент масиву з масиву в javascript.

Наприклад,

Розглянемо наступні твердження.

var arrayElementToDelete = new Object();

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

delete arrayElementToDelete["status"];

Останній рядок коду видалить з масиву елемент масиву, ключовим словом якого є "статус".


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

Не маючи циклів / ітерацій, ми отримуємо той же результат


0

Для "масивів":

Якщо ви знаєте індекс:

array.splice(index, 1);

Якщо вам відомо значення:

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

Відповідь, яка найбільше сподобається, deleteдобре працює у випадку об’єктів, але не для реальних масивів. Якщо я використовую, deleteвін видаляє елементи з циклів, але зберігає елемент як emptyі довжина масиву не змінюється. Це може бути проблемою в деяких сценаріях.

Наприклад, якщо я після видалення через myArray.toString () на myArray deleteстворює порожній запис, тобто ,,


0

Єдиний метод роботи для мене:

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

використання:

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

Чому б замість цього не використовувати фільтр? це ідеальний випадок використання фільтра
— Code Maniac
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.