Удалить свойство для всех объектов в массиве

Я хочу удалить свойство bad из каждого объекта в массиве. Есть ли лучший способ сделать это, чем использовать цикл for и удалять его из каждого объекта?

var array = [{"bad": "something", "good":"something"},{"bad":"something", "good":"something"},...];

for (var i = 0, len = array.length; i < len; i++) {
  delete array[i].bad;
}

Просто кажется, что должен быть способ использовать prototype или что-то в этом роде. Я не знаю. Идеи?


person Zack Argyle    schedule 08.08.2013    source источник
comment
Не имеет значения, другие способы не могут быть меньше линейного O(n). Что бы вы ни использовали, потребуется доступ ко всем вашим элементам массива.   -  person Brian    schedule 08.08.2013
comment
Прототип? Как это поможет? Или все эти объекты являются экземплярами одного и того же конструктора и имеют общее значение для bad?   -  person Bergi    schedule 08.08.2013
comment
@Bergi Интересно, имели ли они в виду прототип JS или прототип Array, примером которого является дистрой?   -  person Ian    schedule 08.08.2013
comment
Я не уверен, что вы должны хранить array.length в переменной перед циклом. Я уверен, вы увидите, что это не стоит боли, если вы профилируете.   -  person Denys Séguret    schedule 08.08.2013
comment
@dystroy Помимо создания еще одной локальной переменной, в чем проблема?   -  person Ian    schedule 08.08.2013
comment
@ian больше кода для чтения. Что касается прототипа, это может быть каждая функция.   -  person Denys Séguret    schedule 08.08.2013
comment
Идея заключалась в том, чтобы найти более быстрый способ, сохранение длины, как правило, быстрее. К сожалению, похоже, что O (n) - единственный способ сделать это. Хромой.   -  person Zack Argyle    schedule 08.08.2013
comment
@ZackArgyle Да, в общем случае быстрее нет ничего.   -  person Denys Séguret    schedule 08.08.2013


Ответы (15)


Единственные другие способы носят косметический характер и на самом деле являются петлями.

Например :

array.forEach(function(v){ delete v.bad });

Примечания:

  • если вы хотите быть совместимым с IE8, вам понадобится прокладка для forEach. Как вы упомянули прототип, прототип.js также имеет прокладку.
  • delete — один из худших "убийцы оптимизации". Его использование часто снижает производительность ваших приложений. Вы не можете избежать этого, если хотите действительно удалить свойство, но часто вы можете либо установить для свойства значение undefined, либо просто создать новые объекты без свойства.
person Denys Séguret    schedule 08.08.2013
comment
Ненамного лучше, чем петля, если петля также может быть фальшивой: P for(var i = 0; i < array.length ) delete array[i].bad - person Esailija; 08.08.2013
comment
@Esailija Зависит. Мне нравится использовать forEach, потому что я нахожу код более выразительным (и потому что я давно перестал беспокоиться об IE). - person Denys Séguret; 08.08.2013
comment
Ни один из них радикально не выражает свойство удаления всех объектов в этом массиве. forEach является общим и семантически бессмысленным сам по себе, как цикл for. - person Esailija; 08.08.2013
comment
@Esailija Я согласен. Вот почему я уточнил, что это косметика. Разве это не ясно в моем ответе? - person Denys Séguret; 08.08.2013
comment
Несчастный. Я буду придерживаться цикла for, который обычно быстрее, чем forEach. И действительно... кого волнует IE8. Спасибо за помощь. - person Zack Argyle; 08.08.2013
comment
Да, цикл for быстрее. Но на самом деле вам не нужно кэшировать длину массива, движок лучше вас справляется с такого рода оптимизациями. - person Denys Séguret; 08.08.2013
comment
Да, наверное, я просто привык к другим языкам программирования, которые значительно повышают производительность. - person Zack Argyle; 08.08.2013
comment
не рекомендуется, см. ответ @piotr_cz stackoverflow.com/a/46839399/5452834 для последнего подхода. - person Fai Zal Dong; 22.10.2019
comment
@FaiZalDong действительно следует избегать использования delete, но этот другой ответ не является ответом. Он не удаляет свойства, а создает новый объект. Добавлю точности, хотя для случаев такой подход возможен. - person Denys Séguret; 22.10.2019

С ES6 вы можете деконструировать каждый объект, чтобы создать новый без именованных атрибутов:

const newArray = array.map(({dropAttr1, dropAttr2, ...keepAttrs}) => keepAttrs)
person piotr_cz    schedule 19.10.2017
comment
Применительно к исходной проблеме это может быть const newArray = array.map(({ bad, ...item }) => item); - person dhilt; 27.09.2018
comment
Это очень рекомендуется, так как он не изменяет исходный массив (неизменяемые операции) - person Pizzicato; 05.04.2019
comment
Это должен быть принятый ответ, потому что он возвращает новый массив, а не перезаписывает существующий. - person user1275105; 11.08.2019
comment
отличный ответ, но не работает, если имя свойства содержит точку (.), например. 'плохая опора' - person Yayati; 17.12.2019
comment
@Amiraslan, я бы использовал // eslint-disable-next-line no-unused-vars - person piotr_cz; 27.02.2020
comment
Я получаю сообщение об ошибке: преобразование круговой структуры в json в этом формате. Есть идеи, почему? - person Apoorva Ambhoj; 07.12.2020
comment
Что делать, если реквизит динамический? И нужно ли удалять его на лету? - person Игор Ташевски; 02.03.2021
comment
@emile Я думаю, что это проблема с машинописным текстом, когда вы опускаете значения с подчеркиванием. - person Игор Ташевски; 17.06.2021
comment
@ИгорТашевски _ - это просто новое имя локального идентификатора, это может быть что угодно, оно просто игнорируется в возвращаемом результате. - person Emile Bergeron; 17.06.2021

Я предпочитаю использовать карту, чтобы удалить свойство, а затем вернуть новый элемент массива.

array.map(function(item) { 
    delete item.bad; 
    return item; 
});
person ex0b1t    schedule 18.11.2015
comment
Имейте в виду, что это мутирует исходный массив - person piotr_cz; 19.10.2017
comment
В этом конкретном случае явный оператор return не требуется. - person Sandeep Kumar; 21.08.2019

Если вы используете underscore.js:

var strippedRows = _.map(rows, function (row) {
    return _.omit(row, ['bad', 'anotherbad']);
});
person Cody    schedule 09.02.2016
comment
_.omit удаляется в Lodash v5, насколько мне известно - person Drenai; 23.07.2021

На мой взгляд это самый простой вариант

array.map(({good}) => ({good}))
person maplemap    schedule 14.01.2019
comment
вопрос был об устранении плохого, а не о сохранении хорошего. Если в ваших объектах есть 10 полей, которые нужно сохранить, и одно, которое нужно удалить, приведенное выше становится очень длинным для ввода. - person adrien; 02.02.2019

Решение с использованием прототипов возможно только тогда, когда ваши объекты похожи:

function Cons(g) { this.good = g; }
Cons.prototype.bad = "something common";
var array = [new Cons("something 1"), new Cons("something 2"), …];

Но тогда все просто (и O(1)):

delete Cons.prototype.bad;
person Bergi    schedule 08.08.2013

Вы можете следовать этому, более читабельному, а не ожиданию повышения из-за того, что ключ не найден:

data.map((datum) => {
  return {
    'id':datum.id,
    'title':datum.login
  }
});
person Maifee Ul Asad    schedule 27.08.2020

Этот вопрос немного устарел, но я хотел бы предложить альтернативное решение, которое не изменяет исходные данные и требует минимальных ручных усилий:

function mapOut(sourceObject, removeKeys = []) {
  const sourceKeys = Object.keys(sourceObject);
  const returnKeys = sourceKeys.filter(k => !removeKeys.includes(k));
  let returnObject = {};
  returnKeys.forEach(k => {
    returnObject[k] = sourceObject[k];
  });
  return returnObject;
}

const array = [
  {"bad": "something", "good":"something"},
  {"bad":"something", "good":"something"},
];

const newArray = array.map(obj => mapOut(obj, [ "bad", ]));

Он по-прежнему не идеален, но поддерживает некоторый уровень неизменности и имеет гибкость, позволяющую называть несколько свойств, которые вы хотите удалить. (Предложения приветствуются)

person James Marks    schedule 03.01.2020

Самый короткий путь в ES6:

array.forEach(e => {delete e.someKey});
person Idan    schedule 09.11.2020

Я предлагаю использовать Object.assign в цикле forEach(), чтобы объекты копировались и не влияли на исходный массив объектов.

var res = [];
array.forEach(function(item) { 
    var tempItem = Object.assign({}, item);
    delete tempItem.bad; 
    res.push(tempItem);
});
console.log(res);
person Ankit Agarwal    schedule 13.12.2018

Это хорошо работает для меня!

export function removePropertiesFromArrayOfObjects(arr = [], properties = []) {
return arr.map(i => {
    const newItem = {}
    Object.keys(i).map(key => {
        if (properties.includes(key)) { newItem[key] = i[key] }
    })
    return newItem
})

}

person Maicon Gilton    schedule 05.03.2021

Я пытался создать новый объект, не удаляя столбцы в Vue.js.

let data =this.selectedContactsDto[];

//selectedContactsDto[] = объект со списком объектов массива, созданных в моем проекте

console.log(данные); let newDataObj= data.map(({groupsList,customFields,firstname, ...item}) => item); console.log("newDataObj", newDataObj);

person Sunali Bandara    schedule 16.04.2020

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

Это функция пользователя, возвращающая объект сведений о пользователе, мы должны удалить ключ api_secret из строк:

    function getCurrentUser(req, res, next) { // user function
    var userId = res.locals.userId;
    console.log(userId)
    db.runSQLWithParams("select * from users where id = $1", [userId], function(err, rows) {
      if(err){
        console.log(err)
      }
      var responseObject = {
        _embedded: rows,
      }
      responseObject._embedded[0].api_secret = undefined
      // console.log(api);
      // console.log(responseObject);
      res.json(responseObject);
    }); 
}

Вышеупомянутая функция возвращает ниже объект как ответ JSON до

 {
    "_embedded": [
        {
            "id": "0123abd-345gfhgjf-dajd4456kkdj",
            "secret_key: "secret",
            "email": "[email protected]",
            "created": "2020-08-18T00:13:16.077Z"
        }
    ]
}

После добавления этой строки responseObject._embedded[0].api_secret = undefined она дает следующий результат в виде ответа JSON:

{
        "_embedded": [
            {
                "id": "0123abd-345gfhgjf-dajd4456kkdj",
                "email": "[email protected]",
                "created": "2020-08-18T00:13:16.077Z"
            }
        ]
    }
person akshay_sushir    schedule 18.08.2020
comment
он возвращает null в массив - person Mohamed Farouk; 08.02.2021
comment
Пожалуйста, поделитесь своим примером кода, если это возможно. Это помогает понять проблему - person akshay_sushir; 11.02.2021

Там полно библиотек. Все зависит от того, насколько сложна ваша структура данных (например, рассмотрите глубоко вложенные ключи).

Нам нравятся object-fields, поскольку он также работает с глубоко вложенными иерархиями (сборка для полей API параметр). Вот простой пример кода

// const objectFields = require('object-fields');

const array = [ { bad: 'something', good: 'something' }, { bad: 'something', good: 'something' } ];

const retain = objectFields.Retainer(['good']);
retain(array);
console.log(array);
// => [ { good: 'something' }, { good: 'something' } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Отказ от ответственности: я являюсь автором object-fields

person vincent    schedule 18.11.2020

person    schedule
comment
Не могли бы вы объяснить свое решение? - person sg7; 02.04.2018
comment
Карта — это новая структура данных в JavaScript ES6. Прикрепленная ссылка может вам помочь. hackernoon.com/what-you-should-know-about- es6-maps-dc66af6b9a1e - person hk_y; 02.04.2018
comment
это решение не подходит, если у вас много реквизита в ваших предметах. - person Koop4; 18.04.2018
comment
Да! Пытался предложить другой подход. - person hk_y; 19.04.2018
comment
В своем комментарии вы путаете Map, структуру данных, которую вы не используете, с Array.prototype.map, методом массива, который вы используете. - person Emile Bergeron; 15.06.2021