Если у меня есть массив строк, я могу использовать .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(", ");
}
В этом коде нет ничего плохого, он работает, но внезапно я перешел от простой, лаконичной строки кода к очень важной функции. Есть ли более сжатый, идеально более функциональный способ написания этого?
javascript
arrays
object
jackweirdy
источник
источник
" ,".join([i.name for i in a])
users.map(x => x.name).join(', ');
.Ответы:
Если вы хотите сопоставить объекты чему-либо (в данном случае это свойство). Я думаю,
Array.prototype.map
это то, что вы ищете, если вы хотите функционально кодировать.В современном JavaScript:
(Скрипка)
Если вы хотите поддерживать более старые браузеры, которые не совместимы с ES5, вы можете их изменить (на странице MDN выше есть полифильтр). Другой альтернативой будет использование
pluck
метода underscorejs :источник
[x.name for x of users]
(spec wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions ). Стоит отметить, что использование карты / редуктора / фильтра не очень «питонно», в отличие от JavaScript. CoffeeScript классен с ними, хотя coffeescript.org .users.map((obj) -> obj.name).join(', ')
Ну, вы всегда можете переопределить
toString
метод ваших объектов:источник
toString
методу всех элементов, используя цикл for. Или вы можете использовать этот подход при работе с функциями конструктора, добавив одинtoString
метод кprototype
свойству конструктора. Однако этот пример должен был показать основную концепцию.Я также сталкивался с использованием
reduce
метода, вот как это выглядит:(a.name || a)
Так первый элемент обрабатывается правильно, но остальное (гдеa
это строка, и такa.name
определены) не рассматриваются как объект.Изменить: я теперь рефакторинг это дальше к этому:
который я считаю чище, как
a
всегда строка,b
всегда является объектом (из-за использования необязательного параметра initialValue вreduce
)Редактировать 6 месяцев спустя: о чем я думал. "очиститель". Я разозлил кодекс богов.
источник
reduce
не так широко поддерживается, какmap
(что странно, учитывая, что они вроде сестры), поэтому я все еще использую ваш ответ :)Я не знаю, есть ли более простой способ сделать это без использования внешней библиотеки, но мне лично нравится underscore.js котором есть множество утилит для работы с массивами, коллекциями и т. Д.
С подчеркиванием вы можете сделать это легко с помощью одной строки кода:
_.pluck(arr, 'name').join(', ')
источник
arr
твой массив, естественно)На узле или ES6 +:
источник
скажем, массив объектов ссылается на переменную
users
Если можно использовать ES6, то самым простым решением будет:
Если нет, то и лодаш можно использовать так:
источник
Если объект и динамические ключи:
"applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}
источник
Старая ветка, которую я знаю, но все еще очень важна для всех, кто сталкивался с этим.
Array.map был предложен здесь, это отличный метод, который я использую все время. Array.reduce был также упомянут ...
Я бы лично использовал Array.reduce для этого варианта использования. Зачем? Несмотря на то, что код немного менее чистый / понятный. Это гораздо эффективнее, чем привязка функции карты к объединению.
Причина этого в том, что Array.map должен перебирать каждый элемент, чтобы возвращать новый массив со всеми именами объекта в массиве. Затем Array.join перебирает содержимое массива, чтобы выполнить соединение.
Вы можете улучшить читабельность Jackweirdys уменьшить ответ, используя литералы шаблона, чтобы код был в одной строке. «Поддерживается во всех современных браузерах»
источник
Не уверен, но все это отвечает тем, что они работают, но не являются оптимальными, поскольку выполняют два сканирования, и вы можете выполнить это за один просмотр. Даже если O (2n) считается O (n), всегда лучше иметь истинное O (n).
Это может выглядеть как старая школа, но позволяет мне делать вот так:
источник
попробуй это
источник
name
атрибут. (a[i].name
Это не использовать вашу функцию вname
аргумент, это эквивалентноa[i]['name']
.)