Skip to content

Instantly share code, notes, and snippets.

@kajic
Created September 26, 2013 18:35
Show Gist options
  • Save kajic/6718600 to your computer and use it in GitHub Desktop.
Save kajic/6718600 to your computer and use it in GitHub Desktop.
Joins ['Uhura', 'Spock', 'Troi', 'Kirk', 'Worf'] into the string 'Uhura, Spock, Troi and 2 others'.
# Public: Join lists into sentence-like strings of the form a, b, c and 2 others.
#
# options - Options hash.
# :max - The maximum number of items to include in the result
# (default: 3).
# :delimiter - Delimiter between items (default: ', ').
# :last_delimiter - Delimiter between the two last items (default: ' and ').
# :others_formatter - Block called to format the '3 others' suffix
# (default: pluralize(count, 'other'))
# &formatter - Block called to format each item (default: item.to_s).
#
# Examples:
#
# sentence_join([:a, :b, :c, :d]) => 'a, b, c and 1 other'
# sentence_join([:a, :b, :c, :d], :max => 2) => 'a, b and 2 others'
# sentence_join([:foo, :bar]) { |item| item.to_s.upcase } => 'FOO and BAR'
#
# others_formatter = lambda { |count| "#{count} more" }
# sentence_join(['foo', 'bar', 'baz', 'qux'], :others_formatter => others_formatter) => 'foo, bar, baz and 1 more'
def sentence_join(items, options={}, &formatter)
options = options.reverse_merge({
:max => 3,
:delimiter => ', ',
:last_delimiter => ' and ',
:others_formatter => lambda {|count| pluralize(count, 'other') }
})
parts = []
items[0...options[:max]].each_with_index do |item, i|
if i > 0
if i + 1 < items.size
parts << options[:delimiter]
else
parts << options[:last_delimiter]
end
end
parts << (block_given? ? formatter.call(item) : item.to_s)
end
if items.size > options[:max]
parts << options[:last_delimiter]
parts << options[:others_formatter].call(items.size - options[:max])
end
parts.join('')
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment