How to join array elements into string with commas & ampersand?

Viewed 1745

In my program given an array of hashes of the name. I want to return a string formatted as a list of names separated by commas except for the last two names, which should be separated by an ampersand.

For e.g.

list([{ name: 'Bart' }, { name: 'Lisa' }, { name: 'Maggie' }]);
// returns 'Bart, Lisa & Maggie'

list([{ name: 'Bart' }, { name: 'Lisa' }]);
// returns 'Bart & Lisa'

list([{ name: 'Bart' }]);
// returns 'Bart'

list([]);
// returns ''

For that, I am mapping values of an array of object using map function and using the slice to extract the last two values of the array and then using toString to convert it into string and then using split("&") to add ampersand between last two elements but I'm not getting output according to expectation.

code:

function list(names){
   let result = names.map(value => value.name);
   return result.slice(-2).toString().split('&');
}

list([{name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'}]);
4 Answers

It's a bit tricker than that, since you'll have to separate out the final name in the list from the rest initially, then join the rest. If there are any in the rest, then concatenate the joined string with ' and ', else return the final name only:

function list(people){
  const names = people.map(({ name }) => name);
  const finalName = names.pop();
  return names.length
  ? names.join(', ') + ' & ' + finalName
  : finalName;
}

console.log(list([ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ])) // returns 'Bart, Lisa & Maggie'
console.log(list([ {name: 'Bart'}, {name: 'Lisa'} ])) // returns 'Bart & Lisa'
console.log(list([ {name: 'Bart'} ])) // returns 'Bart'

Note that the input is not an array of names - it's an array of objects that need to be mapped to names later, so you might name your variables more precisely and give list an argument of people (or something like that) rather than names.

You can pop the last item from the array, join the remaining items using a comma and then append the last item with an ampersand. Updated code:

function list(names) {
   if (names.length === 0) return '';
   if (names.length === 1) return names[0].name; 
   let result = names.map(value => value.name);
   let lastName = result.pop();
   return result.join(', ') + ' & ' + lastName;
}

let string = list([{name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'}]);

console.log(string);

Only enter code herey two condition :

  • if only one name in the list
  • or more than one name in list

function myCustomList(persons){
  names = persons.map(({ name }) => name);
  lastName = names.pop();
  return names.length ? names.join(', ') + ' & ' + lastName : lastName;
}
//watch your answer in alert box

alert(myCustomList([ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ]));

You're on the right track; join is the missing ingredient and is perfect for delimited lists.

Edge cases are when there is only one or no names in the list and require extra conditionals to handle. A couple other answers in this thread don't handle empty lists gracefully.

const list = names =>
  names.slice(0, -1).map(e => e.name).join(", ") +
  (names.length > 1 ? " & " : "") +
  (names.length ? names[names.length-1].name : "")
;

console.log(list([{name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'}]));
console.log(list([{name: 'Bart'}, {name: 'Lisa'}]));
console.log(list([{name: 'Bart'}]));
console.log(list([]));

That said, I'd probably generalize the function to avoid the hardcoded .name key, adding that as a separate preprocessing step:

const commaJoin = a => 
  a.slice(0, -1).join(", ") +
  (a.length > 1 ? " & " : "") +
  (a.length ? a.at(-1) : "")
;

const nameToList = list => commaJoin(list.map(e => e.name));

console.log(nameToList([{name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'}]));
console.log(nameToList([{name: 'Bart'}, {name: 'Lisa'}]));
console.log(nameToList([{name: 'Bart'}]));
console.log(nameToList([]));

console.log(commaJoin(["foo", "bar"]));

Related