Выполнить .join по значению в массиве объектов
Если у меня есть массив строк, я могу использовать метод .join()
чтобы получить одну строку с каждым элементом, разделенным запятыми, например:
["Joe", "Kevin", "Peter"].join(", ") // => "Joe, Kevin, Peter"
У меня есть массив объектов, и я хотел бы выполнить аналогичную операцию со значением, содержащимся в нем; так из
[
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
]
выполнить метод join
только для атрибута name
, чтобы получить тот же результат, что и раньше.
В настоящее время у меня есть следующая функция:
function joinObj(a, attr){
var out = [];
for (var i = 0; i < a.length; i++){
out.push(a[i][attr]);
}
return out.join(", ");
}
В этом коде нет ничего плохого, он работает, но внезапно я перешел от простой, лаконичной строки кода к очень важной функции. Есть ли более сжатый, идеально более функциональный способ написания этого?
Ответы
Ответ 1
Если вы хотите сопоставить объекты с чем-либо (в данном случае это свойство). Я думаю, что Array.prototype.map
- это то, что вы ищете, если хотите кодировать функционально.
[
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
].map(function(elem){
return elem.name;
}).join(",");
В современном JavaScript:
[
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
].map(e => e.name).join(",");
(скрипка)
Если вы хотите поддерживать более старые браузеры, которые не совместимы с ES5, вы можете их отменить (на странице MDN выше указан полифильтр). Другой альтернативой может быть использование метода pluck
underscorejs:
var users = [
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
];
var result = _.pluck(users,'name').join(",")
Ответ 2
Ну, вы всегда можете переопределить метод toString
ваших объектов:
var arr = [
{name: "Joe", age: 22, toString: function(){return this.name;}},
{name: "Kevin", age: 24, toString: function(){return this.name;}},
{name: "Peter", age: 21, toString: function(){return this.name;}}
];
var result = arr.join(", ");
//result = "Joe, Kevin, Peter"
Ответ 3
Я также сталкивался с использованием метода reduce
, вот как он выглядит:
[
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
].reduce(function (a, b) {return (a.name || a) + ", " + b.name})
(a.name || a)
, поэтому первый элемент обрабатывается правильно, а остальное (где a
- строка, поэтому a.name
is undefined) не рассматривается как объект.
Изменить: теперь я отредактировал его дальше:
x.reduce(function(a, b) {return a + ["", ", "][+!!a.length] + b.name;}, "");
который, я считаю, более чистым, поскольку a
всегда является строкой, b
всегда является объектом (из-за использования необязательного параметра initialValue /a > in reduce
)
Редактировать 6 месяцев спустя: О, о чем я думал. "очиститель". Я разозлил код Богов.
Ответ 4
Я не знаю, есть ли более простой способ сделать это, не используя внешнюю библиотеку, но я лично люблю underscore.js, у которой есть множество утилит для работы с массивами, коллекциями и т.д.
С подчеркиванием вы можете сделать это легко с помощью одной строки кода:
_.pluck(arr, 'name').join(', ')
Ответ 5
Вкл. node или ES6:
users.map(u => u.name).join(', ')
Ответ 6
позволяет сказать, что массив объектов ссылается на переменную users
Если ES6 можно использовать, самым простым решением будет:
users.map(user => user.name).join(', ');
Если нет, и lodash можно использовать так:
_.map(users, function(user) {
return user.name;
}).join(', ');
Ответ 7
Если объект и динамические ключи: "applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}
Object.keys(myObject).map(function (key, index) {
return myObject[key]
}).join(', ')
Ответ 8
Старая ветка, которую я знаю, но все еще очень важна для всех, кто сталкивался с этим
Здесь был предложен Array.map, который является замечательным методом, который я использую все время. Array.reduce был также упомянут...
Я бы лично использовал Array.reduce для этого варианта использования. Зачем? Несмотря на то, что код немного менее чистый/понятный. Это гораздо эффективнее, чем отправка функции карты в соединение.
Причина этого в том, что Array.map должен перебирать каждый элемент для возврата нового массива со всеми именами объекта в массиве. Затем Array.join перебирает содержимое массива, чтобы выполнить соединение.
Вы можете улучшить читабельность jackweirdys и уменьшить ответ, используя литералы шаблонов для переноса кода в одну строку. "Поддерживается во всех современных браузерах"
// a one line answer to this question using modern JavaScript
x.reduce((a, b) => '${a.name || a}, ${b.name}');
Ответ 9
Не уверен, но все это отвечает тем, что они работают, но не являются оптимальными, так как выполняют два сканирования, и вы можете выполнить это в одном сканировании. Даже если O (2n) считается O (n), всегда лучше иметь истинное O (n).
const Join = (arr, separator, prop) => {
let combined = '';
for (var i = 0; i < arr.length; i++) {
combined = '${combined}${arr[i][prop]}';
if (i + 1 < arr.length)
combined = '${combined}${separator} ';
}
return combined;
}
Это может выглядеть как старая школа, но позволяет мне делать вот так:
skuCombined = Join(option.SKUs, ',', 'SkuNum');
Ответ 10
попробуйте это
var x= [
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
]
function joinObj(a, attr) {
var out = [];
for (var i=0; i<a.length; i++) {
out.push(a[i][attr]);
}
return out.join(", ");
}
var z = joinObj(x,'name');
z > "Joe, Kevin, Peter"
var y = joinObj(x,'age');
y > "22, 24, 21"