5

I want to create an array of n number of distinct empty subarrays.

Is this the best way?

Array.new(n){ [] }

It was as follows, but I modified after reading comments:

Array.new(n){ |_| [] }

I tried:

Array.new(n, [])

but it creates an array with all the subarrays being the same object, which I do not want.

10
  • Another way: n.times.map { |_| [] } Commented Aug 20, 2018 at 4:49
  • 7
    Slightly more succinct: Array.new(n){[]} Commented Aug 20, 2018 at 4:49
  • 3
    Smells like XY problem. Maybe you need Matrix? Commented Aug 20, 2018 at 4:53
  • 4
    @Neddy: Note also that if you have subarrays - empty or not - the "parent" array is not empty. Commented Aug 20, 2018 at 6:00
  • 3
    "an empty array of empty sub arrays" is a self-contradiction. An empty array contains nothing. Commented Aug 20, 2018 at 8:17

3 Answers 3

4

All the proposed method to get this array [[], [], [],...] works fine:

Array.new(n, []) # the best, 20 times faster
Array.new(n){ [] }
n.times.map { [] }

The first is the fastest, so the best, but works strangely (see next).

it created an array with all the sub arrays being the same object

If i get the point, you mean that whit the methods described happens what follows:

a = Array.new(5, [])
p a # => [[], [], [], [], [], [], [], [], [], []]
p a.map { |e| e.object_id} # => [70189488740180, 70189488740180, 70189488740180, 70189488740180, 70189488740180]]

The object is the same, so if you try to fill subarrays with values, all of the subarrays assume the same value (replication):

a[0][0] = 10
p a # => [[10], [10], [10], [10], [10]]

To avoid this don't pass a default value, but map to empty array instead:

a = Array.new(5).map{ |e| [] }
p a # => [[], [], [], [], []]

Or pass the block

a = Array.new(5){ [] }
a = 5.times.map { [] }

Now each subarray is an independent object:

p a.map { |e| e.object_id} # => [70253023825640, 70253023825620, 70253023825600, 70253023825580, 70253023825560]

And if you insert some values there is no replication:

a[0][0] = 10
a[1][0] = 20
p a # => [[10], [20], [], [], []]
Sign up to request clarification or add additional context in comments.

4 Comments

Why use map when you can simply pass a block to new as shown in the beginning?
@Stefan Ooops! Edit. Thanks. But I'm still not sure about what's the OP issue.
The original question was "is there a better way than Array.new(n){ |_| [] }", so the OP probably just wanted to know if there is a shorthand syntax to create an array of empty arrays.
Array.new(n, []) is not the best, and the question explains why it doesn't work (all the subarrays are the same object).
2

Array.new(n) { [] } is totally fine!
The block ensures that a new instance of Array is created n times. As you pointed out, you would otherwise reference the same object (instance of Array) n times.

1 Comment

This is what I am going with, I wasn't sure if there was a more correct way to do this, but it appears not. Thank you!
0

Please try this. It work for me.

  n = 15
  arr = Array.new(n)
  arr.map!{ |x| x = [] }

Now, putting value in the array.

arr[0][0] = 10 
arr[5][0] = 50
p arr # => [[10], [], [], [], [], [50], [], [], [], [], [], [], [], [], []]

1 Comment

The assignment in x = [] is superfluous, you just need arr.map!{ [] }. Which is merely Array.new(n) { [] } on two lines.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.