Patrick Oscity
Patrick Oscity

Reputation: 54674

RoR / Ruby delete nil elements from nested array

To split an array into two equal pieces I would do this,

>> a = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
>> a.in_groups_of( (a.size/2.0).ceil ) if a.size > 0
=> [[1, 2, 3], [4, 5, nil]]

Now I've got a nested array that contains nil elements if the size of the array is odd. How can I remove the nil elements from the nested arrays? I want to do something like,

a.compact

But unfortunately that doesn't work, ruby only removes nil elements on the first level and not recursively. Does ruby provide any nice solutions for this problem?

Upvotes: 14

Views: 15691

Answers (5)

Frank
Frank

Reputation: 71

arr_mixed=['hello', 2222, 'world', nil, [1, 2, 5, 'hi', nil],[1, 2, 3], [4,   5, nil]]

def compact_nested(array)
   arr2=[]
   array.each { |x|
   element = x.class==Array ? x.compact : x
   arr2<<element
   }
   arr2
end

p compact_nested(arr_mixed).compact #=>["hello", 2222, "world", [1, 2, 5, "hi"], [1, 2, 3], [4, 5]]
p arr_mixed #=>["hello", 2222, "world", nil, [1, 2, 5, "hi", nil], [1, 2, 3], [4, 5, nil]]

Upvotes: 0

Phil Ross
Phil Ross

Reputation: 26090

With Ruby 1.8.7 and later you can do the following:

a.each &:compact!
=> [[1, 2, 3], [4, 5]]

With Ruby 1.8.6, you have do do this the long way:

a.each {|s| s.compact!}

Both of these will modify the contents of a. If you want to return a new array and leave the original alone, you can use collect instead of each:

# 1.8.7+:
a.collect &:compact

# 1.8.6:
a.collect {|s| s.compact}

Upvotes: 44

Ryan Bigg
Ryan Bigg

Reputation: 107718

If you were to use the in_groups_of you can pass it false as the second argument and it will not fill in the "blanks" with nil, but truly nothing.

Upvotes: 8

Sniggerfardimungus
Sniggerfardimungus

Reputation: 11831

a.each {|subarray| subarray.compact!}
a.compact!

Should work....

Upvotes: -3

Steinbitglis
Steinbitglis

Reputation: 2614

Unless you want to permanently change a

a.map do |e|
  e.compact
end

Upvotes: 3

Related Questions