Ashish Jambhulkar
Ashish Jambhulkar

Reputation: 1494

Remove trailing nil values from array in ruby

I have an array something like this:

[["a", nil, nil, nil], ["b", nil, "c", nil], [nil, nil, nil, nil]]

I want to remove all trailing nil values from array in ruby.

I tried arr.map {|x| x.pop until x.last} but the problem with this approach is that when all the value of arrays are nil like in 3rd array in given array, the loop stucks.

Because of the until x.last condition, If all the values are nil then the map function should return me an empty array?

What should be the conditions for this.

The output should be

[['a'],['b','nil','c'],[]]

Remember I just want to remove trailing nil values not in between.

Upvotes: 13

Views: 1134

Answers (3)

Ilya
Ilya

Reputation: 13477

One more option is to use rindex:

arr.map do |e| 
  index =  e.rindex { |i| !i.nil? } # the last index of not `nil` element
  index ? e.first(index + 1) : e 
end
#=> [["a"], ["b", nil, "c"], []]

Upvotes: 4

Ilya
Ilya

Reputation: 13477

You are on the right way, but just modify your code a bit:

array.each { |e| e.pop until !e.last.nil? || e.empty? }
#=> [["a"], ["b", nil, "c"], []]

It's faster than using reverse-reverse and drop_while.

Upvotes: 10

Fire Lancer
Fire Lancer

Reputation: 30115

For this you can forget about the outer array and solve it for just the inner arrays, then use map to apply the solution to all of them.

drop_while will return a new array without all leading items that met some condition (e.g. nil?). You wanted trailing however so combine with reverse.

[nil,nil,5,nil,6,nil].reverse.drop_while(&:nil?).reverse
[nil, nil, 5, nil, 6]

Then use map for all the arrays.

arr = [["a", nil, nil, nil], ["b", nil, "c", nil], [nil, nil, nil, nil]]
arr.map{|a| a.reverse.drop_while(&:nil?).reverse}
[["a"], ["b", nil, "c"], []]

If you do want any remaining nil to actually be a string, you could combine it with another map performing any such conversion you like.

Upvotes: 14

Related Questions