Как удалить объекты из ассоциативного массива JavaScript?

Предположим, у меня есть такой код:

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

Если бы я хотел удалить "фамилию"? .... есть ли какой-нибудь эквивалент myArray["lastname"].remove()?

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

Совет: не путайте массивы и карты. Некоторые языки, например php, имеют один объект для обоих. Хотя вы использовали здесь правильный тип (new Object ()), вы назвали его myArray, это просто вопрос стандартов для языка.

Juan Mendes 27.04.2010 21:35

Не забывайте, что JavaScript не имеет типов и все является объектом. См. Ответ Саула ниже.

Steve K 15.06.2012 13:24

@StephanKristyn - если быть точным, в JS есть типы, но в стиле динамичный и слабый. Например, хотя его переменные действительно не имеют типа, их значения - нет. Это часть динамичный. Слабый означает, что операции между разными типами значений не определены строго и полагаются на скрытые преобразования; например, "Test" + {}; - это совершенно корректный оператор JS.

Saul 27.08.2012 12:46
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
646
3
631 865
17
Перейти к ответу Данный вопрос помечен как решенный

Ответы 17

Ответ принят как подходящий

Объекты в 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 к оптимизироватькод.

Это вызовет проблемы при использовании в экземпляре объекта Array для удаления существующего элемента, например. delete myArray[0]. См. stackoverflow.com/a/9973592/426379 и Удаление элементов массива.

Saul 02.04.2012 13:43

Какие проблемы возникнут?

Gottox 02.04.2012 14:01

@Gottox - свойство length объекта Array остается неизменным.

Saul 02.04.2012 14:53

@Saul: есть проблемы с бы, если myArray действительно использовался как массив - но это не так (myArray - неудачное имя), это объект. Так что в этом случае delete в порядке. Обратите внимание, что даже если бы он был создан как new Array() и использовался как ассоциативный массив, он все равно был бы в порядке. Ваше предупреждение по-прежнему нужно знать, если вы используете реальные массивы.

johndodo 04.04.2012 11:47

@johndodo - Верно. Вот почему я начал свой первоначальный комментарий с Это вызовет проблемы если, используемый в экземпляре объекта Множество. Тем не менее я предпочитаю подход, который работает правильно во всех случаях, см. Мой ответ ниже.

Saul 04.04.2012 13:19

@Saul: см. Мой комментарий под вашим ответом.

johndodo 04.04.2012 17:33

@kamal - нет. Что хотите можно найти здесь

user416527 17.01.2013 02:04

Правильно ли его использовать, если элемент не существует в массиве?

Ivan Kochurkin 17.02.2013 16:27

Удаляет ли это также объекты, на которые есть ссылки? Что, если myArray ["lastname"] был ссылкой?

whiterook6 03.06.2014 00:45

@ whiterook6 В Javascript нет ничего "деструктора". Поведение «удаления» простое и просто делает следующую переменную неопределенной.

Dennis C 01.07.2014 10:11

Работает с объектами. Массивы будут иметь неопределенные значения.

Ben Affleck 26.08.2014 17:44

Что происходит, когда вы пытаетесь удалить несуществующий атрибут?

Kevin Wheeler 21.07.2015 20:26

Что, если я хочу удалить «фамилию» из 3D-массива?

Vaishnavi Patel 06.03.2019 12:49

В JavaScript нет многомерных массивов. Однако возможны вложенные массивы.

Ben Aston 19.04.2020 13:14

Все объекты в JavaScript реализованы в виде хэш-таблиц / ассоциативных массивов. Итак, следующие эквиваленты:

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

И, как уже указывалось, вы «удаляете» свойство из объекта с помощью ключевого слова delete, которое можно использовать двумя способами:

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

Надеюсь, дополнительная информация поможет ...

Следует отметить, что точечная нотация не работает, если свойство не является простым термином. то есть myObj['some;property'] работает, а myObj.some;property - нет (по понятным причинам). Также может быть неочевидно, что вы можете использовать переменную в обозначении скобок, то есть var x = 'SomeProperty'; alert(myObj[x]).

Kip 27.04.2011 07:48

«Все объекты в JavaScript реализованы в виде хэш-таблиц / ассоциативных массивов.» - false. V8 предпочитает хранить объект как скрытый класс + плотно упакованные поля. Только если вы делаете с ними странные вещи (например, удаляете поля), он сдаётся и использует хэш-карту за кулисами.

John Dvorak 19.08.2015 09:08

@JanDvorak - эй, ты узнал, когда был написан этот ответ, да? Это описание было и остается достаточным для большинства целей. Тем не менее, я понимаю, что это утомительно педантично. :)

Jason Bunting 10.11.2015 23:23

При этом удаляется только объект, но длина массива остается неизменной.

Чтобы удалить элемент из массива, вам нужно сделать что-то вроде:

array.splice(index, 1);

В самом деле, но в этом случае массив не используется, просто старый простой объект, поэтому у него нет длины или метода сращивания.

MooGoo 13.09.2010 07:48

@Andreaa Panagiotidis За исключением случаев, когда мы говорим о массивах, и в этом случае это неверно в 100% случаев ?

Drenai 31.05.2018 04:32

Вы используете 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
    }

Ни один из предыдущих ответов не касается того факта, что JavaScript не имеет ассоциативных массивов для начала - нет типа array как такового, см. typeof.

В JavaScript есть экземпляры объектов с динамическими свойствами. Когда свойства путают с элементами экземпляра объекта Array, неизбежно происходят Плохие Вещи ™:

Проблема

var elements = new Array()

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

console.info("number of elements: ", elements.length)   // Returns 2
delete elements[1]
console.info("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.info("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.info(elements.length)                        // Returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.info(elements.hasOwnProperty("prop"))        // Returns false as it should
console.info(elements.length)                        // returns 1 as it should

У этого решения есть две проблемы: оно скрывает тот факт, что массивы и объекты - это совершенно разные звери в JS (вы это знаете, но, по-видимому, OP нет), и оно использует прототипы. OP было бы лучше, если бы он узнал о массивах и объектах (и называл бы свои переменные соответственно) - попытка скрыть различия между ними только доставит ему больше проблем. ИМХО конечно.

johndodo 04.04.2012 17:38

@johndodo - все Array в JS являются объектами, попробуйте typeof new Array(); или typeof [] для проверки. Array - это просто объект определенного типа, а вовсе не «другой зверь». В JS объекты различаются по имени конструктора и цепочке прототипов, см. Программирование на основе прототипов.

Saul 05.04.2012 10:53

Вы упускаете суть. Я знаю, что массивы тоже являются объектами, но это не значит, что их разумно использовать как таковые. Программист должен решить, хочет ли он использовать что-либо как массив (с push, pop, [], ...) или как объект / «ассоциативный массив». Смешивать и сочетать - не лучший рецепт именно из-за проблем, которые ваше решение пытается скрыть. Если вы заранее решите, какой шаблон проектирования использовать (массив или объект), таких проблем не будет.

johndodo 05.04.2012 12:06

@johndodo - О каких конкретно проблемах ты говоришь? Целью приведенного выше кода является устранение недостатка оператора delete в отношении Array путем предоставления простой полиморфной функции.

Saul 05.04.2012 13:25
delete не имеет дефицита. delete предназначен для удаления свойств. Вот и все. Применение оператора удаления к индексу массива удаляет этот индекс. Что еще нужно сделать? У вас остается разреженный массив, что является особенностью языка. Если вам не нужен разреженный массив, не удаляйте индекс: используйте splice или pop.
Ben Aston 19.04.2020 13:18

@BenAston Да, глядя на это сейчас, после стольких лет, я согласен. Разреженные массивы действительно являются особенностью языка, а удаление действительно просто предназначено для удаления свойств. Теперь все, что мне нужно сделать, это выяснить, как найти мотивацию для удаления ответа, который принес мне около 450 очков репутации :-)

Saul 19.04.2020 23:29

@BenAston Да ... или 442 балла, если быть точным. Так что, кто знает, может быть, некоторые из этих голосов были даны не за "обходной путь", а за некоторые полезные идеи в целом :-) В любом случае, спасибо за внимание к дезинформированным частям и разъяснениям!

Saul 20.04.2020 17:40

Хотя принятый ответ правильный, в нем отсутствует объяснение, почему он работает.

Прежде всего, ваш код должен отражать тот факт, что это нет массив:

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

Обратите внимание, что таким образом можно использовать все объекты (включая Array). Однако не стоит ожидать, что стандартные функции массива JavaScript (pop, push и т. д.) Будут работать с объектами!

Как сказано в принятом ответе, вы можете использовать delete для удаления записей из объектов:

delete myObject["lastname"]

Вы должны решить, какой маршрут вы хотите выбрать - либо использовать объекты (ассоциативные массивы / словари), либо использовать массивы (карты). Никогда не смешивайте их двоих.

Очень хороший ответ. Я бы посоветовал всем, кто читает это, не абстрагировать массивы в javascript как «карты», а скорее как «списки». Это потому, что вы не должны пытаться контролировать индекс элементов при использовании массивов. Если ты попробуешь это ... ну, только не надо: D

rodolfo42 04.05.2014 07:13

Как отмечали другие ответы, вы используете не массив JavaScript, а объект JavaScript, который работает почти как ассоциативный массив на других языках, за исключением того, что все ключи преобразуются в строки. Новый карта хранит ключи как их исходный тип.

Если у вас есть массив, а не объект, вы можете использовать функцию массива .фильтр, чтобы вернуть новый массив без элемента, который вы хотите удалить:

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

Если у вас более старый браузер и jQuery, в jQuery есть метод $.grep, который работает аналогично:

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

прекрасное объяснение. Я использовал фильтр, чтобы добиться желаемого результата. Не могли бы вы объяснить, как работает возвращаемый элемент для удаления объекта из массива. Я предполагаю, что он возвращает массив, если он не включает строку, которую вы включили.

Edward 19.01.2018 19:05

Если по какой-либо причине клавиша удаления не работает (например, у меня она не работает), вы можете разделить ее, а затем отфильтровать неопределенные значения:

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

Не пытайтесь соединить их в цепочку, так как splice возвращает удаленные элементы;

Это очень просто, если в вашем проекте есть зависимость Underscore.js -

_.omit(myArray, "lastname")

Используя ключевое слово "delete", он удалит элемент массива из массива в JavaScript.

Например,

Рассмотрим следующие утверждения.

var arrayElementToDelete = new Object();

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

delete arrayElementToDelete["status"];

Последняя строка кода удалит из массива элемент, ключ которого имеет значение «status».

Вы можете удалить запись с карты, явно присвоив ей значение undefined. Как и в вашем случае:

myArray["lastname"] = undefined;

Это может быть полезно в тех случаях, когда кто-то не уверен, существует ли ключ в словаре, но хочет очистить его, если он есть. Поправьте меня, если я ошибаюсь, Амитис.

Hassan Baig 13.06.2018 00:27

Используйте метод 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");

это более общее решение, его можно добавить в ваш файл js, и метод будет доступен для всех массивов, а не только для одного массива.

Hussain 29.06.2017 15:24

Мы также можем использовать его как функцию. Angular выдает некоторую ошибку, если используется в качестве прототипа. Спасибо @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");
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);

Без цикла / итераций мы получаем тот же результат.

В Руководстве по стилю Airbnb есть элегантный способ сделать это (ECMAScript 7):

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

Авторское право: https://codeburst.io/use-es2015-object-rest-operator-to-omit-properties-38a3ecffe90

Для «Массивов»:

Если вы знаете индекс:

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, он создает пустую запись, то есть ,,.

Единственный рабочий метод для меня:

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 11.08.2019 19:06

Другие вопросы по теме