Tscott
Tscott

Reputation: 485

Calling specific element from array not returning (Ruby)

I can't tell what's wrong with my code:

def morse_code(str)
    string = []
    string.push(str.split(' '))
    puts string
    puts string[2]
end

What I'm expecting is if I use "what is the dog" for str, I would get the following results:

=> ["what", "is", "the", "dog"]
=> "the"

But what I get instead is nil. If I do string[0], it just gives me the entire string again. Does the .split function not break them up into different elements? If anyone could help, that would be great. Thank you for taking the time to read this.

Upvotes: 0

Views: 61

Answers (1)

Arup Rakshit
Arup Rakshit

Reputation: 118261

Your code should be :

def morse_code(str)
  string = []
  string.push(*str.split(' '))
  puts string
  p string[2]
end

morse_code("what is the dog" )
# >> what
# >> is
# >> the
# >> dog
# >> "the"

str.split(' ') is giving ["what", "is", "the", "dog"], and you are pushing this array object to the array string. Thus string became [["what", "is", "the", "dog"]]. Thus string is an array of size 1. Thus if you want to access any index like 1, 2 so on.., you will get nil. You can debug it using p(it calls #inspect on the array), BUT NOT puts.

def morse_code(str)
  string = []
  string.push(str.split(' '))
  p string
end

morse_code("what is the dog" )
# >> [["what", "is", "the", "dog"]]

With Array, puts works completely different way than p. I am not good to read MRI code always, thus I take a look at sometime Rubinious code. Look how they defined IO::puts, which is same as MRI. Now look the specs for the code

it "flattens a nested array before writing it" do
    @io.should_receive(:write).with("1")
    @io.should_receive(:write).with("2")
    @io.should_receive(:write).with("3")
    @io.should_receive(:write).with("\n").exactly(3).times
    @io.puts([1, 2, [3]]).should == nil
  end

  it "writes nothing for an empty array" do
    x = []
    @io.should_receive(:write).exactly(0).times
    @io.puts(x).should == nil
  end

  it "writes [...] for a recursive array arg" do
    x = []
    x << 2 << x
    @io.should_receive(:write).with("2")
    @io.should_receive(:write).with("[...]")
    @io.should_receive(:write).with("\n").exactly(2).times
    @io.puts(x).should == nil
  end

We can now be sure that, IO::puts or Kernel::puts behaves with array just the way, as Rubinious people implemented it. You can now take a look at the MRI code also. I just found the MRI one, look the below test

  def test_puts_recursive_array
    a = ["foo"]
    a << a
    pipe(proc do |w|
      w.puts a
      w.close
    end, proc do |r|
      assert_equal("foo\n[...]\n", r.read)
    end)
  end

Upvotes: 2

Related Questions