Reputation: 16521
I have an array d = ['foo', 'bar', 'baz']
, and want to put its elements together into a string delimited by ,
and and
at the last element so that it will become foo, bar and baz
.
Here is what I'm trying to do:
s = ''
d.each_with_index { |x,i|
s << x
s << i < d.length - 1? i == d.length - 2 ? ' and ' : ', ' : ''
}
but the interpreter gives an error:
`<': comparison of String with 2 failed (ArgumentError)
However, it works with +=
instead of <<
, but the Ruby Cookbook says that:
If efficiency is important to you, don't build a new string when you can append items onto an existing string. [And so on]... Use
str << var1 << ' ' << var2
instead.
Is it possible without +=
in this case?
Also, there has to be a more elegant way of doing this than the code above.
Upvotes: 1
Views: 745
Reputation: 15478
So much simpler like this:
"#{d[0...-1].join(", ")} and #{d.last}"
Upvotes: 1
Reputation: 81450
I'd find
s << i < d.length - 1? i == d.length - 2 ? ' and ' : ', ' : ''
hard to read or maintain.
I'd probably change it to
join = case
when i < d.length - 2 then ", "
when i == d.length - 2 then " and "
when i == d.length then ""
end
s << join
Or possibly do
earlier_elements = d[0..-2].join(", ")
s = [earlier_elements, d[-1..-1]].join(" and ")
Or
joins = [", "] * (d.length - 2) + [" and "]
s = d.zip(joins).map(&:join).join
Upvotes: 4
Reputation: 31077
You're just missing some parenthesis:
d = ['foo', 'bar', 'baz']
s = ''
d.each_with_index { |x,i|
s << x
s << (i < d.length - 1? (i == d.length - 2 ? ' and ' : ', ') : '')
}
Upvotes: 5