11

I'm going through an online lesson, which usually has a very simple one line solution. A problem states that, given the following array:

["emperor", "joshua", "abraham", "norton"]

I must use #inject to get a single string of all names joined together with a string, each name initial capped, like this:

"Emperor Joshua Abraham Norton"

While this could easily be done with #map and #join, this particular exercise requires the use of #inject only. I came up with something like this:

["emperor", "joshua", "abraham", "norton"].inject("") do |memo, word|
   memo << word.capitalize << " "
end

which would give me:

"Emperor Joshua Abraham Norton "

where the whitespace at the end of the string doesn't pass as the correct solution.

  • How do I achieve this without the whitespace at the end?
  • Is this even the right way to use #inject, passing an empty string?
  • Am I making correct use of the << to combine strings?
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
Darek Rossman
  • 1,323
  • 1
  • 10
  • 12
  • 1
    Good and described in details question as for beginner – megas Mar 14 '12 at 13:30
  • Thanks for all the answers! I know it seems silly to use #inject in this case, but it's just one of those exercises meant to test your understanding of the concepts and not necessarily your ability to find the shortest and most efficient solution. – Darek Rossman Mar 14 '12 at 13:50

6 Answers6

10

Try this:

a.map{|t| t.capitalize}.join(" ")

I don't think you can escape from the extra space with inject. Also you need to do

memo = memo + word.capitalize + " " 

EDIT: as the statement has changed to force you not to use join and map, here is a bit ugly solution with inject:

a.inject("") do |memo, world|
  memo << " " unless memo.empty?
  memo << word.capitalize
end
Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
2
a = ["emperor", "joshua", "abraham", "norton"]
a.drop(1).inject(a.first.capitalize){|res,m| res << ' '+m.capitalize }
megas
  • 21,401
  • 12
  • 79
  • 130
  • Thanks for the response! I edited my original question to clarify that this exercise requires the use of #inject. It specifically says not to use #map and #join. – Darek Rossman Mar 14 '12 at 13:35
  • Oh that's interesting...thanks! Can you explain the use of << after res and the + before m.capitalize? Is there a difference between the two in this case? – Darek Rossman Mar 14 '12 at 13:54
  • 1
    ' '+m.capitalize will return " Joshua" and it adds to initial value "Emperor". The result of operation will be "Emperor Joshua" which will be passed to the next iteration. – megas Mar 14 '12 at 13:59
  • Close, but the first element is added twice. The code results in "Emperor Emperor Joshua Abraham Norton". Should work if you call `inject` on `a[1..-1]`. – user1252434 Mar 15 '12 at 08:21
1

There are better ways then #inject, see the other answers. But if you insist you could just String#rstrip the trailing space character.

Or turn the block around and check whether memo is empty before adding the character.

memo << " " unless memo.empty?
memo << name.capitalize

I'm not sure about the << operator. I would use +, but that is probably just be a personal preference.

user1252434
  • 2,083
  • 1
  • 15
  • 21
1

Checking to add " " every turn is more expensive then to chop! last output. Your choise about << is true you can look string concatenation.

%w(emperor joshua abraham norton).inject("") do |m,w|
  m << w.capitalize << " "
end.chop!
"Emperor Joshua Abraham Norton"
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
Selman Ulug
  • 867
  • 5
  • 17
0

puts x.inject { |memo, val| "#{memo} #{val.upcase}" }

0

Don't use #inject , there are better ways to solve that:

["emperor", "joshua", "abraham", "norton"].map(&:capitalize).join(' ')

Your first objective should always be to solve the problem at hand. You could use #inject, but it's just not the ideal, or even clear, solution here. You have better things to do with your time than try to figure out how to trick #inject into giving you the right results.

Community
  • 1
  • 1
wersimmon
  • 2,809
  • 3
  • 22
  • 35
  • I would, however, suggest asking this question on the [Code Golf SE](http://codegolf.stackexchange.com/), just to see what people come up with. – wersimmon Mar 14 '12 at 13:30
  • The problem states that while it could (and should) easily be done with #map and #join, it wants you to use #inject. The exercise is meant to give you an understanding of what these methods do and how they work. – Darek Rossman Mar 14 '12 at 13:31
  • So test your understanding with a problem that makes sense: like "add all the numbers from 1 to 100, but subtract numbers divisible by 5". – wersimmon Mar 14 '12 at 13:43