DanielSD DanielSD - 2 months ago 6
Ruby Question

ruby operator confusion with shovel (<<) and += , Concating arrays

I've read some of the differences between << +=. But i think i may not understand these differences, because my expected code doesn't output what i want to achieve.

in response to Ruby differences between += and << to concatenate a string

I want to unscramble "Cat" into an array of its letters/words
=> ["c", "ca", "cat", "a", "at", "t"]

def helper(word)
words_array = []
idx = 0
while idx < word.length
j = idx
temp = ""
while j < word.length
**temp << word[j]**
words_array << temp unless words_array.include?(temp)
j += 1
idx += 1
p words_array

I don't understand why
temp << word[j]
is different from temp += word[j] when to me my logic in this specific case is correct.


One difference is that because << works in place it is somewhat faster than +=. The following code

require 'benchmark'

a = ''
b= ''

puts Benchmark.measure {
  100000.times { a << 'test' }

puts Benchmark.measure {
  100000.times { b += 'test' }


0.000000   0.000000   0.000000 (  0.004653)
0.060000   0.060000   0.120000 (  0.108534)


I originally misunderstood the question. Here's whats going on. Ruby variables only store references to objects, not the objects themselves. Here's simplified code that does the same thing as yours, and has the same issue. I've told it to print temp and words_array on each iteration of the loops.

def helper(word)
  words_array = []

  word.length.times do |i|
    temp = ''
    (i...word.length).each do |j|
      temp << word[j]
      puts "temp:\t#{temp}"
      words_array << temp unless words_array.include?(temp)
      puts "words:\t#{words_array}"


p helper("cat")

Here is what it prints:

temp:   c
words:  ["c"]
temp:   ca
words:  ["ca"]
temp:   cat
words:  ["cat"]
temp:   a
words:  ["cat", "a"]
temp:   at
words:  ["cat", "at"]
temp:   t
words:  ["cat", "at", "t"]
["cat", "at", "t"]

As you can see, during each iteration of the inner loop after the first, ruby is simply replacing the last element of words_array. That is because words_array holds a reference to the string object referenced by temp, and << modifies that object in place rather than creating a new object.

On each iteration of the outer loop temp is set to a new object, and that new object is appended to words_array, so it doesn't replace the previous elements.

The += construct returns a new object to temp on each iteration of the inner loop, which is why it does behave as expected.