18

How can I turn an array, such as ["Susy", "John", "Mary"] to "Susy, John, and Mary" in Javascript? I can't get Ruby's to_sentence method out of my head.

1
  • 4
    not so seriously, but.. ["Susy", "John", "Mary"].join(',').split(/,M/).join(' and M'); Commented Feb 8, 2013 at 1:07

12 Answers 12

24

Using newest JavaScript (Chrome 72+):

new Intl.ListFormat().format(["Susy", "John", "Mary"]);

which will result in:

"Susy, John, and Mary"
Sign up to request clarification or add additional context in comments.

2 Comments

Whoa, this is going to be great, when it's supported! developers.google.com/web/updates/2018/12/intl-listformat
Awesome! But unfortunately still poorly supported by other browsers :( caniuse.com/#search=ListFormat
14

Join all items except the last one, and then add that:

var s = arr.slice(0, arr.length - 1).join(', ') + ", and " + arr.slice(-1);

Demo: http://jsfiddle.net/JYKcK/1/

7 Comments

Just one note- Americans put a comma before the "and". OP has done this.
@popnoodles: Ah, then you would just use + ", and " +.
I can see a couple of problems with this method. If there's only 1 element in the array, it will return ", and Susy". For two elements, it returns "Susy, and John", which isn't grammatically correct.
@Alex: Yes, with less that three items you need additional code, but that's outside the scope of the question. There is no answer here that handles that case.
Good point, but I think if you're only concerned with the specific use case presented, you could end up with something like jAndy's (joke) answer :-) I've posted an answer that covers the most obvious cases I could think of.
|
11

Another option, using Array.prototype.reduce, would be:

var arr = [1,2,3];
arr.reduce(
  function(prev, curr, i){ 
    return prev + curr + ((i===arr.length-2) ? ' and ' : ', ')
  }, '')
.slice(0, -2);

Produces "1, 2 and 3".

Comments

6
toSentence = function(arr){ return arr.join(", ").replace(/,\s([^,]+)$/, ' and $1');};

toSentence(['dogs', 'cats']);           // => dogs and cats

toSentence(['dogs', 'cats', 'snakes']); // => dogs, cats and snakes

Comments

6

There are a few extra cases in this one:

  1. Do we want to have a comma before the "and" (Oxford Comma)
  2. Either way, we don't want a comma if there are only 2 elements
  3. If there is only 1 element, we just want that word returned

I think this fits all of those use cases:

function joinSentence( array, oxford_comma ){
  if( array.length > 1 ){
    var lastWord = " and " + array.pop();
    if( oxford_comma && array.length > 1 ){
      lastWord = "," + lastWord;
    }
  }else{
    var lastWord = "";
  }
  return array.join(", ") + lastWord;
}

Comments

3

And another solution:

(function(a) {
    var b = (a||(a=[])).pop(); 
    return (b ? a.length ? [a.join(", "),b] : [b] : a).join(" and ");
})(["Susy", "John", "Mary"]);

or just defining your ruby-like sentence method in array's prototype:

Array.prototype.sentence = function(comma,and) {
    var b = this.pop();
    return (b ? this.length ? [this.join(comma||", "),b] : [b] : this).join(and||" and ");
};

["Susy", "John", "Mary"].sentence(); 
//"Susy, John and Mary"

["Susy", "John", "Mary"].sentence(" and ", " as well as "); 
//"Susy and John as well as Mary"

["Susy", "John", "Mary", "Helmut"].sentence(); 
//"Susy, John, Mary and Helmut"

Comments

2

modify the last then join

var source = ["Susy", "John", "Mary"];
source.push( 'and ' +source.pop());
console.log(source.join(', '))// Susy, John, and Mary

2 Comments

ok this is sexier :) But is it grammatically correct to add a comma before and?
Doesn't work for 1 and 2 elements: ["Susy"] => "and Susy". ["Susy", "John"] => "Susy, and John"
2

Try that:

var array = ['susy', 'john', 'mary'];
var last = array.pop();
var string = array.join(', ') + " and " + last;

i didn t try but you should get the idea

Comments

1

You can use .join() and prepend the last value with an "and"

var array = ['susy', 'john', 'mary'];

array[array.length-1] = 'and '+array[array.length-1];

//string is "susy, john, and mary"
var string = array.join(', ');

2 Comments

I know of this method, I'm wanting "and" before the last item.
my bad, I didn't see the "and"... let me re-factor
0

There is actually an easier way these days, just use method join(); For example, let array = ["Susy", "John", "Mary"]; array.join(); This will return Susy,John,Mary

Comments

0

A very simple way to do it:

function toSentence(array) {
  const lastWord = (array.length > 1) ? ` and ${array.pop()}` : ''
  return array.join(', ') + lastWord
}

Comments

-2
var arr = ["Susy", "John", "Mary"];
var str = arr.join(", ");

1 Comment

This produces "Susy, John, Mary", which is not the desired result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.