У меня есть массив объектов JavaScript со следующей структурой:
objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];
Я хочу извлечь поле из каждого объекта, и получить массив, содержащий значения, например поле foo
даст массив [ 1, 3, 5 ]
.
Я могу сделать это с помощью этого тривиального подхода:
function getFields(input, field) {
var output = [];
for (var i=0; i < input.length ; ++i)
output.push(input[i][field]);
return output;
}
var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]
Есть ли более элегантный или идиоматический способ сделать это, чтобы пользовательская функция полезности была бы ненужной?
Обратите внимание на предложенный дубликат , он описывает, как преобразовать один объект в массив.
var foos = objArray.pluck("foo");
.Array.prototype.map
функцию там, где она существуетОтветы:
Вот более короткий способ достижения этого:
ИЛИ
Вы также можете проверить
Array.prototype.map()
.источник
Да, но он основан на функции ES5 JavaScript. Это означает, что он не будет работать в IE8 или старше.
На ES6-совместимых интерпретаторах JS вы можете использовать функцию стрелки для краткости:
Документация Array.prototype.map
источник
foo
?var result = objArray.map((a) => (a.foo));
var result = objArray.map(a => a.foo);
Проверьте функцию Лодаша
_.pluck()
или функцию Подчеркивания_.pluck()
. Оба делают именно то, что вы хотите в одном вызове функции!Обновление:
_.pluck()
удалено с Lodash v4.0.0 в пользу_.map()
в сочетании с чем-то похожим на ответ Ниета ._.pluck()
все еще доступен в Underscore .Обновление 2: Как отмечает Марк в комментариях , где-то между Lodash v4 и 4.3, была добавлена новая функция, которая снова предоставляет эту функцию.
_.property()
является сокращенной функцией, которая возвращает функцию для получения значения свойства в объекте.Кроме того,
_.map()
теперь разрешается передача строки в качестве второго параметра, в который передается_.property()
. В результате следующие две строки эквивалентны приведенному выше примеру кода из предварительной версии 4._.property()
и, следовательно_.map()
, также позволяет вам предоставить строку или массив, разделенные точками, для доступа к под-свойствам:Оба
_.map()
вызова в приведенном выше примере вернутся[5, 2, 9]
.Если вы немного больше разбираетесь в функциональном программировании, взгляните на
R.pluck()
функцию Рамды , которая выглядит примерно так:источник
_.property('foo')
( lodash.com/docs#property ) было добавлено сокращениеfunction(o) { return o.foo; }
. Это сокращает вариант использования Lodash доvar result = _.pluck(objArray, _.property('foo'));
Для дальнейшего удобства_.map()
метод Lodash 4.3.0 также позволяет использовать сокращение_.property()
под капотом, что приводит кvar result = _.map(objArray, 'foo');
Говоря о решениях только для JS, я обнаружил, что, как ни крути, простой индексированный
for
цикл более производительный, чем его альтернативы.Извлечение одного свойства из массива элементов 100000 (через jsPerf)
Традиционный для цикла 368 Ops / sec
ES6 для ... 303 Ops / сек
Array.prototype.map 19 операций в секунду
TL; DR - .map () медленный, но не стесняйтесь использовать его, если считаете, что читаемость стоит больше, чем производительность.
Edit # 2: 6/2019 - ссылка на jsPerf сломана, удалена.
источник
Лучше использовать какие-то библиотеки, такие как lodash или underscore для межбраузерной гарантии.
В Lodash вы можете получить значения свойства в массиве следующим способом
и в нижней части
Оба вернутся
источник
Использование
Array.prototype.map
:См. Ссылку выше для прокладки для браузеров до ES5.
источник
В ES6 вы можете сделать:
источник
Хотя
map
это правильное решение для выбора «столбцов» из списка объектов, у него есть и обратная сторона. Если явно не проверено, существуют ли столбцы, это выдаст ошибку и (в лучшем случае) предоставит вамundefined
. Я бы выбралreduce
решение, которое может просто игнорировать свойство или даже установить значение по умолчанию.пример jsbin
Это будет работать, даже если один из элементов в предоставленном списке не является объектом или не содержит поле.
Это может быть даже сделано более гибким путем согласования значения по умолчанию, если элемент не является объектом или не содержит поле.
пример jsbin
Это будет то же самое с картой, так как длина возвращаемого массива будет такой же, как предоставленный массив. (В этом случае a
map
немного дешевле, чем areduce
):пример jsbin
Кроме того, существует наиболее гибкое решение, позволяющее переключаться между двумя вариантами поведения, просто предоставляя альтернативное значение.
пример jsbin
Поскольку вышеприведенные примеры (надеюсь) проливают некоторый свет на то, как это работает, давайте немного сократим функцию, используя
Array.concat
функцию.пример jsbin
источник
В общем, если вы хотите экстраполировать значения объекта, которые находятся внутри массива (как описано в вопросе), вы можете использовать уменьшение, отображение и деструктуризацию массива.
ES6
Эквивалентное использование для цикла in :
Произведенный вывод: ["word", "again", "some", "1", "2", "3"]
источник
Это зависит от вашего определения «лучше».
Другие ответы указывают на использование карты, которая является естественной (особенно для парней, привыкших к функциональному стилю) и лаконичной. Я настоятельно рекомендую использовать его (если вы не беспокоитесь о нескольких парнях из IE8). Так что, если «лучше» означает «более краткий», «поддерживаемый», «понятный», тогда да, это намного лучше.
С другой стороны, эта красота не обходится без дополнительных затрат. Я не большой поклонник микровыступов, но я провел небольшой тест здесь . Результат предсказуем, старый уродливый способ кажется быстрее, чем функция карты. Так что, если «лучше» означает «быстрее», то нет, оставайтесь со старой школьной модой.
Опять же, это всего лишь микробук и никоим образом не выступает против использования
map
, это всего лишь мои два цента :).источник
map
это простой путь, так или иначе я просто не смог найти его с помощью Google (я нашел только карту jquery, которая не имеет отношения к делу).Если вы хотите также поддерживать массивоподобные объекты, используйте Array.from (ES2015):
Преимущество метода Array.prototype.map () в том, что входные данные также могут быть Set :
источник
Если вы хотите несколько значений в ES6 +, будет работать следующее
Это работает как
{foo, baz}
на левом используют объект destructoring и на правой стороне стрелки эквивалентно{foo: foo, baz: baz}
из - за усиленные литералы объектов ES6 в .источник
Карта функций - хороший выбор при работе с массивами объектов. Хотя уже было опубликовано несколько хороших ответов, пример использования карты с комбинацией с фильтром может быть полезным.
Если вы хотите исключить свойства, значения которых не определены, или исключить только определенное свойство, вы можете сделать следующее:
https://jsfiddle.net/ohea7mgk/
источник
Приведенный выше ответ хорош для извлечения одного свойства, что если вы хотите извлечь более одного свойства из массива объектов. Вот решение !! В этом случае мы можем просто использовать _.pick (object, [paths])
Предположим, что у objArray есть объекты с тремя свойствами, как показано ниже
Теперь мы хотим извлечь свойства foo и bar из каждого объекта и сохранить их в отдельном массиве. Сначала мы будем перебирать элементы массива, используя map, а затем применяем к нему метод Lodash Library Standard _.pick ().
Теперь мы можем извлечь свойства 'foo' и 'bar'.
var newArray = objArray.map((element)=>{ return _.pick(element, ['foo','bar'])}) console.log(newArray);
и результат будет [{foo: 1, bar: 2}, {foo: 3, bar: 4}, {foo: 5, bar: 6}]
наслаждаться!!!
источник
_.pick
берутся? Это не стандартная функция.Если у вас есть вложенные массивы, вы можете заставить их работать так:
источник