Perform .join on value in array of objects

Perform .join on value in array of objects

If I have an array of strings, I can use the .join() method to get a single string, with each element separated by commas, like so:
[“Joe”, “Kevin”, “Peter”].join(“, “) // => “Joe, Kevin, Peter”

I have an array of objects, and I’d like to perform a similar operation on a value held within it; so from
{name: “Joe”, age: 22},
{name: “Kevin”, age: 24},
{name: “Peter”, age: 21}

perform the join method only on the name attribute, to achieve the same output as before.
Currently I have the following function:
function joinObj(a, attr){
var out = [];

for (var i = 0; i < a.length; i++){ out.push(a[i][attr]); } return out.join(", "); } There’s nothing wrong with that code, it works, but all of a sudden I’ve gone from a simple, succinct line of code to a very imperative function. Is there a more succinct, ideally more functional way of writing this?


Solution 1:

If you want to map objects to something (in this case a property). I think is what you’re looking for if you want to code functionally.

  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}

In modern JavaScript:

  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
].map(e =>",");


Related:  Remove non-numeric characters except points, commas and '$'?

If you want to support older browsers, that are not ES5 compliant you can shim it (there is a polyfill on the MDN page above). Another alternative would be to use underscorejs’s pluck method:

var users = [
      {name: "Joe", age: 22},
      {name: "Kevin", age: 24},
      {name: "Peter", age: 21}
var result = _.pluck(users,'name').join(",")

Solution 2:

Well you can always override the toString method of your objects:

var arr = [
    {name: "Joe", age: 22, toString: function(){return;}},
    {name: "Kevin", age: 24, toString: function(){return;}},
    {name: "Peter", age: 21, toString: function(){return;}}

var result = arr.join(", ");
//result = "Joe, Kevin, Peter"

Solution 3:

I’ve also come across using the reduce method, this is what it looks like:

  {name: "Joe", age: 22},
  {name: "Kevin", age: 24},
  {name: "Peter", age: 21}
].reduce(function (a, b) {return ( || a) + ", " +})

The ( || a) is so the first element is treated correctly, but the rest (where a is a string, and so is undefined) isn’t treated as an object.

Related:  Password validation is at least 6 character

Edit: I’ve now refactored it further to this:

x.reduce(function(a, b) {return a + ["", ", "][+!!a.length] +;}, "");

which I believe is cleaner as a is always a string, b is always an object (due to the use of the optional initialValue parameter in reduce)

Edit 6 months later: Oh what was I thinking. “cleaner”. I’ve angered the code Gods.

Solution 4:

I don’t know if there’s an easier way to do it without using an external library, but I personally love underscore.js which has tons of utilities for dealing with arrays, collections etc.

With underscore you could do this easily with one line of code:

_.pluck(arr, 'name').join(', ')

Solution 5:

On node or ES6: =>', ')

Solution 6:

lets say the objects array is referenced by the variable users

If ES6 can be used then the easiest solution will be: =>', ');

If not, and lodash can be used so :, function(user) {
 }).join(', ');