Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Strings - difference between << and +=

Running the method fizzbuzz1 yields a 100 member list of numbers 1 to 100, where each multiple of 3 is replaced by "fizz", each multiple of 5 by "buzz", and each multiple of both 3 and 5 by "fizzbuzz":

def fizzbuzz1()
  result = Array.new(100, "")
  result.each_index do |index|
    value = index + 1
    result[index] += "fizz" if value % 3 == 0
    result[index] += "buzz" if value % 5 == 0
    result[index] = "#{value}" if result[index].size == 0
  end
end

2.0.0-p195 :055 > fizzbuzz1
 => ["1", "2", "fizz", "4", "buzz", "fizz", "7", "8", "fizz", ...and so on.

BUT, switching each += for a << yields something unexpected:

def fizzbuzz2()
  result = Array.new(100, "")
  result.each_index do |index|
    value = index + 1
    result[index] << "fizz" if value % 3 == 0
    result[index] << "buzz" if value % 5 == 0
    result[index] = "#{value}" if result[index].size == 0
  end
end

2.0.0-p195 :057 > entire_fizzbuzz2_result = fizzbuzz2
2.0.0-p195 :058 > entire_fizzbuzz2_result[5]
 => "fizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzz" 

Most peculiarly, I also notice that if I take out the line: result[index] = "#{value}" if result[index].size == 0 to give:

def fizzbuzz3()
  result = Array.new(100, "")
  result.each_index do |index|
    value = index + 1
    result[index] << "fizz" if value % 3 == 0
    result[index] << "buzz" if value % 5 == 0
  end
end

2.0.0-p195 :062 > store_fizzbuzz3 = fizzbuzz3
2.0.0-p195 :063 > store_fizzbuzz3.reject { |each| store_fizzbuzz3[0] == each }
 => [] 

Which must mean that fizzbuzz3 returns a 100 member array where each element is the same, and has the characteristics:

2.0.0-p195 :066 > store_fizzbuzz3[1]
 => "fizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzzfizzfizzbuzzfizzbuzzfizzfizzbuzz" 
2.0.0-p195 :067 > store_fizzbuzz3[1].size
 => 212 
2.0.0-p195 :068 > store_fizzbuzz3[1].size / 4
 => 53 

And 53 is a sort of interesting number in that it is the number of integers between 1 and 100 that are not divisible by 3 or 5...i.e. the number of "numbers" in the result of the fully functioning fizzbuzz1 up top.

What is going on here with the <<, could someone give me a little walkthrough?

like image 355
polpetti Avatar asked Dec 06 '25 14:12

polpetti


1 Answers

There are two interacting matters here:

  1. The form of Array.new(), and
  2. The style of string concatenation.

In the form you use, Array.new(100, "") creates an Array with 100 elements, each pointing to the same empty string. += returns a new string, so that doesn't matter. << appends to the existing string, so it does matter that they're all the same.

If you initialize result with this form of Array.new():

result = Array.new(100){""}

then fizzbuzz2 will work as expected, because you have 100 different empty strings.

like image 171
Darshan Rivka Whittle Avatar answered Dec 08 '25 07:12

Darshan Rivka Whittle



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!