1

I have data for a table of contents:

array = [
  ['Chapter 1', 'Numbers', 1],
  ['Chapter 2', 'Letters', 72],
  ['Chapter 3', 'Variables', 118]
]

I am trying to display the contents of the array as a table like this:

Chapter 1     Numbers       1
Chapter 2     Letters      72
Chapter 3     Variables   118

Here is my code:

lineWidth = 80
col1Width = lineWidth/4
col2Width = lineWidth/2
col3Width = lineWidth/4

array.each do |i|
  puts i[0].to_s.ljust(col1Width) + puts i[1].to_s.ljust(col2Width) + puts i[2].to_s.ljust(col3Width)
end

The problem is I keep getting this error:

chapter7-arrays.rb:48: syntax error, unexpected tIDENTIFIER, expecting keyword_do or '{' or '('
    puts i[0] + puts i[1] + puts i[2]
                      ^
chapter7-arrays.rb:48: syntax error, unexpected tIDENTIFIER, expecting keyword_do or '{' or '('
    puts i[0] + puts i[1] + puts i[2]

All help appreciated.

2 Answers 2

2

Your code is almost correct. The issue is that you are concatenating multiple puts call, whereas you should concatenate the String arguments, and use a single puts call.

array = [['Chapter 1', 'Numbers', 1],['Chapter 2', 'Letters', 72],['Chapter 3', 'Variables', 118]]

lineWidth = 80
col1Width = lineWidth/4
col2Width = lineWidth/2
col3Width = lineWidth/4

array.each do |i|
    puts i[0].to_s.ljust(col1Width) +
         i[1].to_s.ljust(col2Width) +
         i[2].to_s.ljust(col3Width)
end
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, Simone! That was embarrassingly "obvious". I am learning to program and this is an interesting phenomena: sometimes the harder I try to solve something, the harder it gets to see the "obvious". It is probably essential to give the brain a rest more frequently...
Since columns 0 and 1 are already strings, there is no need to call to_s on them. The puts would reduce to i[0].ljust(col1Width) + i[1].ljust(col2Width) + i[2].ljust(col3Width)
@DanielCukier to_s is required for the third index, otherwise you'll try to call ljust on a Fixnum.
@SimoneCarletti exactly. I forgot to put in code. Here is the right one: i[0].ljust(col1Width) + i[1].ljust(col2Width) + i[2].to_s.ljust(col3Width)
1

I've added an explanation according to request from dgilperez

We have an array of sub-arrays with three elements in each. And we have three different formatting values for each item in a sub-array. It is convenient to store formatting values in an array too.

lines = [lineWidth/4, lineWidth/2, lineWidth/4]

Now we need to manage a loop for each sub-array

array.each do |i| 
  i.map
end

...and we need an index of the current element to get respective formatting value.

array.each do |i| 
  i.map.with_index
end

Now we implement a block which is executed for each item z of sub-array

i.map.with_index{|z, index| z.to_s.ljust(lines[index])}

... and index is in a range [0,1,2]. So for the first item we will use the first formatting value, etc

index == 0, lines[index] == lineWidth/4

index == 1, lines[index] == lineWidth/2

This block returns an array of strings because we organized a loop via function map. Check map method documentation here

Now we need to concatenate all the strings into one with method join

i.map.with_index{|z, index| z.to_s.ljust(lines[index])}.join 

And return the final string - add method puts before the block

puts i.map.with_index{|z, index| z.to_s.ljust(lines[index])}.join

Here is the final code

array = [['Chapter 1', 'Numbers', 1],['Chapter 2', 'Letters', 72],['Chapter 3', 'Variables', 118]]

lineWidth = 80
lines = [lineWidth/4, lineWidth/2, lineWidth/4]

array.each do |i| 
  puts i.map.with_index{|z, index| z.to_s.ljust(lines[index])}.join
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.