Erik Madsen
Erik Madsen

Reputation: 2014

join enumerable to produce string in Ruby

Ruby arrays have the #join method that produces a string by joining the elements of the array, adding an optional separator.

Other enumerables such as ranges don't have the same method.

You could emulate the behaviour using #inject, e.g.

('a'..'z').inject('') do |acc, s| 
  if acc.empty?
    s
  else
    acc << ' some separator ' << s.to_s  
  end
end

Is there a better way to join enumerables? Was #join omitted for a particular reason?

EDIT:

One thing I would be concerned about would be copying a massive enumerable to an array. Of course that's seldom a use case, but still. For instance:

(1 .. 1_000_000_000_000_000).to_a.join

Therefore I'm particularly interested in solutions that don't require generating an array with all the values as an intermediate step.

Upvotes: 2

Views: 1179

Answers (3)

Ja͢ck
Ja͢ck

Reputation: 173572

The code within your question is already as optimal as it gets, but it's possible to remove the condition inside your block:

e = ('a'..'z').to_enum

joined_string = e.reduce { |acc, str| acc << ' some separator ' << str }.to_s

Without passing an argument to #reduce, the first time the block gets called, acc and str would represent the first two elements of the enumerable. The additional .to_s at the end is to ensure that an empty string is returned if the enumerable is empty.

Upvotes: 1

Gagan Gami
Gagan Gami

Reputation: 10251

> [*'a'..'z'] * ' some separator '

#=> "a some separator b some separator c some separator d some separator e some separator f some separator g some separator h some separator i some separator j some separator k some separator l some separator m some separator n some separator o some separator p some separator q some separator r some separator s some separator t some separator u some separator v some separator w some separator x some separator y some separator z"

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Use Array#join:

('a'..'z').to_a.join(' some separator ')

Or (effectively the same):

[*'a'..'z'].join(' some separator ')

Upvotes: 3

Related Questions