I tried to create a nested array, but when I update one of them, all other arrays seems to be updated, What am I doing wrong?
arr = Array.new(5,Array.new())
# => [[], [], [], [], []]
arr[0]
# => []
arr[0].push(1)
# => [1]
arr
# => [[1], [1], [1], [1], [1]]
You could use the block syntax to initialize the array:
arr = Array.new(5) { Array.new }
=> [[], [], [], [], []]
arr[0].push(1)
arr
=> [[1], [], [], [], []]
map produces the array:
arr = 5.times.map { [] }
arr.first << 42
#⇒ [42]
arr
#⇒ [[42], [], [], [], []]
Related
Response list returns empty nested array: [[], [], []]
How better test with ruby that following nested array is empty?
You can use Array#empty?
To check all nested arrays are empty with Array#all?
[[], [], []].all?(&:empty?)
# => true
[[1], [2], []].all?(&:empty?)
# => false
[[1], [2], [3]].all?(&:empty?)
# => false
To check at least one nested is empty with Array#any?
[[], [], []].any?(&:empty?)
# => true
[[1], [2], []].any?(&:empty?)
# => true
[[1], [2], [3]].any?(&:empty?)
# => false
If you want to handle deeply nested arrays, you probably want to flatten your array first:
[[], [], []].flatten.empty?
=> true
[[], [[], [[]]]].flatten.empty?
=> true
[[], [[], [[1]]]].flatten.empty?
=> false
I have the following array:
#master = Array.new(4, Array.new(2, Array.new()))
=> [[[], []], [[], []], [[], []], [[], []]]
I'm attempting to assign the very first most value with:
#master[0][0] = "x"
=> "x"
But this is doing a multi assignment
#master
=> [["x", []], ["x", []], ["x", []], ["x", []]]
How do I assign only the first value? I'm hoping to get the following Array:
#master
=> [["x", []], [[], []], [[], []], [[], []]]
In that way you use the same reference for every sub array. Try this way
#master = Array.new(4) { Array.new(2) { Array.new } }
You are creating one array an assigning it to every element of the first array; try running this code:
#master.each { |e| puts e.object_id }
Output (your ids will be different):
70192803217260
70192803217260
70192803217260
70192803217260
As you can see, is the exact same object, so try using #master = Array.new(4) { Array.new(2) { Array.new() } } instead, which will create a new array for each item in the first array.
This question already has answers here:
Why does array.each behavior depend on Array.new syntax?
(3 answers)
Closed 5 years ago.
Can anyone explain this to me:
irb(main):001:0> a = Array.new(3, [])
=> [[], [], []]
irb(main):001:0> b = [[], [], []]
=> [[], [], []]
irb(main):003:0> a.each_with_index{ |r, idx| r << 'a' }
=> [["a", "a", "a"], ["a", "a", "a"], ["a", "a", "a"]]
irb(main):004:0> b.each_with_index{ |r, idx| r << 'a' }
=> [["a"], ["a"], ["a"]]
When using the .new method:
Since all the Array elements store the same hash, changes to one of them will affect them all.
If multiple copies are what you want, you should use the block version which uses the result of that block each time an element of the array needs to be initialized:
2.3.0 :001 > a = Array.new(3) { [] }
=> [[], [], []]
2.3.0 :002 > a.each_with_index{ |r, idx| r << 'a' }
=> [["a"], ["a"], ["a"]]
Read the examples here - https://ruby-doc.org/core-2.2.0/Array.html#method-c-new
Recently I attempted to append a number to one of the nested arrays in my script.
I expected only the nested array at the specified index to have the number appended to it, but what actually happened was that all of the nested arrays had the number appended to them.
This behaviour seems very odd, why do ruby arrays function this way?
irb(main):001:0> [1,2,3].push 3
=> [1, 2, 3, 3]
irb(main):002:0> layered = [[]] * 5
=> [[], [], [], [], []]
irb(main):003:0> layered[0] << 2
=> [2]
irb(main):004:0> layered
=> [[2], [2], [2], [2], [2]]
irb(main):005:0>
Because all of them are the same array. You can check it by calling Object#object_id on each element:
[3] pry(main)> layered = [[]] * 5
=> [[], [], [], [], []]
[4] pry(main)> layered[0].object_id
=> 70207042910540
[5] pry(main)> layered[1].object_id
=> 70207042910540
[6] pry(main)> layered[2].object_id
=> 70207042910540
To create new array for each element then use Array.new(5) { [] }.
Given an array of length N, how I can I equally distribute the elements of the array into another array of arbitrary length?
For instance, I have 3 items in an array and I'd like it distributed evenly across another array of 9 slots.
[1, 2, 3]
should result in (something close to)
[[], [], [1], [], [], [2], [], [], [3]]
However, if I have 9 items to distribute to an array length of 2, it should result in
[[1,2,3,4], [5,6,7,8,9]]
Thanks!
NOTE: The position of the resulting array items could differ according to the algorithm, but the intent is to get some level of uniform distribution. In the first example, the 0th item could be [1]. In the second example, the 0th item could have [1,2,3,4,5].
Here's an easy way to do that:
def distribute(arr, slots)
n = arr.size
a = Array.new(slots) { [] }
arr.each_with_index { |e,i| a[i*slots/n] << e }
a
end
distribute([1,2,3], 9)
#=> [[1], [], [], [2], [], [], [3], [], []]
distribute([*(1..9)], 2)
#=> [[1, 2, 3, 4, 5], [6, 7, 8, 9]]
You could change the distributions that result by modifying i*slots/n.
So there are two totally different use cases here, one where you have to build an array of length n, the other where you need to split into an array of length n.
This feels like a homework assignment but I don't really have enough off these two use cases to see a pattern (unless I'm missing something huge).
Test cases:
it 'splits on n vals' do
arr = [1,2,3]
expect(chunk(arr, 9)).to eq [[], [], [1], [], [], [2], [], [], [3]]
end
it 'splits on n vals' do
arr = [1,2,3,4,5,6,7,8,9]
expect(chunk(arr,2)).to eq [[1,2,3,4,5],[6,7,8,9]]
end
Code:
def chunk(arr, num)
if num < arr.length
return arr.each_slice( (arr.size/num.to_f).round).to_a
end
array = []
len = arr.length
(0..num).each do |i|
if (i % len == 0) && i != 0
array[i-1] = [arr.first]
array[i] = []
arr.shift
else
array[i] = []
end
end
array.pop
array
end