I'm using Ruby 1.9.2-p290 and found:
a = Array.new(2, []).each {|i| i.push("a")}
=> [["a", "a"], ["a", "a"]]
Which is not what I would expect. But the following constructor style does do what I would expect:
b = Array.new(2) {Array.new}.each {|i| i.push("b")}
=> [["b"], ["b"]]
Is the first example the expected behavior?
In ruby-doc it looks like my size=2
argument is the same kind of argument for both constructors. I think that if the each
method is getting passed that argument that it would use it the same way for both constructors.
A Fortran array variable can be one of four major types: explicit-shape, assumed-shape, deferred-shape, and assumed-size. The runtime descriptor for the first three types makes that array variable's size known at compile time or at runtime. The last dimension of an assumed-size array is the length of its variable.
An array in JavaScript is also an object and variables only hold a reference to an object, not the object itself. Thus both variables have a reference to the same object.
Arrays are used when there is a need to use many variables of the same type. It can be defined as a sequence of objects which are of the same data type. It is used to store a collection of data, and it is more useful to think of an array as a collection of variables of the same type. Arrays can be declared and used.
The syntax of the for...in loop is: for (key in object) { // body of for...in } In each iteration of the loop, a key is assigned to the key variable. The loop continues for all object properties. Note: Once you get keys, you can easily find their corresponding values.
This is a common misunderstanding. In your first example you are creating an array with 2 elements. Both of those are a pointer to the same array. So, when you iterate through your outer array you add 2 elements to the inner array, which is then reflected in your output twice
Compare these:
> array = Array.new(5, [])
=> [[], [], [], [], []]
# Note - 5 identical object IDs (memory locations)
> array.map { |o| o.object_id }
=> [70228709214620, 70228709214620, 70228709214620, 70228709214620, 70228709214620]
> array = Array.new(5) { [] }
=> [[], [], [], [], []]
# Note - 5 different object IDs (memory locations)
> array.map { |o| o.object_id }
=> [70228709185900, 70228709185880, 70228709185860, 70228709185840, 70228709185780]
In the first case you're using a single instance of an Array as a default for the elements of the main Array:
a = Array.new(2, []).each {|i| i.push("a")}
The second argument is simply recycled, so the push
is applied to the same instance twice. You've only created one instance here, the one being supplied as an argument, so it gets used over and over.
The second method is the correct way to do this:
b = Array.new(2) {Array.new}.each {|i| i.push("b")
This deliberately creates a new instance of an Array for each position in the main Array. The important difference here is the use of the block { ... }
which executes once for each position in the new Array. A short-form version of this would be:
b = Array.new(2) { [ ] }.each {|i| i.push("b")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With