Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Should take an array such as ['dog', 'cat', 'bird', 'monkey'] and return 'dog, cat, bird and monkey'.

Looking for a more elegant solution.

def self.english_join(array)
  return nil if array.nil?
  return array[0] if array.length == 1
  return array[0..-2].join(', ') + " and " + array[-1] if array.length > 1
end
share|improve this question

3 Answers 3

up vote 14 down vote accepted

Rails (actually ActiveSupport, part of the Rails framework) offers a very nice Array#to_sentence method.

If you are using Rails or ActiveSupport, you can call

['dog', 'cat', 'bird', 'monkey'].to_sentence
# => "dog, cat, bird, and monkey"

The method is automatically customized according to I18n settings. For example, in Italy you should omit the last comma before the and.

['dog', 'cat', 'bird', 'monkey'].to_sentence
# => "dog, cat, bird e monkey"

If you want something without depending on ActiveSupport, you can start using the method source code.

This is just an example

class Array
  def to_sentence
    default_words_connector     = ", "
    default_two_words_connector = " and "
    default_last_word_connector = ", and "

    case length
      when 0
        ""
      when 1
        self[0].to_s.dup
      when 2
        "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
      else
        "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
    end
  end
end
share|improve this answer
    
.to_sentence is literally magic. –  drusepth Jul 9 '14 at 15:52
def english_join(array = nil)
  return array.to_s if array.nil? or array.length <= 1
  array[0..-2].join(", ") + " and " + array[-1]
end

A similar but different approach. Combines the joining of a slice of the array with a string append to get the last "and" part.

share|improve this answer
2  
However, it might be better to write the last line as "#{array[0..-2].join(", ")} and #{array.last}". "#{}" creates fewer String objects than +, and so should generally be preferred. –  Marnen Laibow-Koser Nov 9 '11 at 16:13
1  
Also, this doesn't get the comma before the "and". –  Marnen Laibow-Koser Nov 9 '11 at 16:14
def self.english_join(array = nil)
  return array.to_s if array.nil? or array.length <= 1
  array[-1] = "and #{array[-1]}"
  array.join(', ')
end

A different way but not much better. Returns an empty string instead of nil if the array is empty. Someone will chime in with a sweet to_sentence method.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.