3

I have two arrays:

a = [nil, 1, nil]
b = [4, 5, 6]

And i want to replace nil elements from first array with related elements from second array:

[4, 1, 6]

What is the best way to do it?

0

5 Answers 5

6

You can use zip and the || operator to do it:

result = a.zip(b).map{ |x,y| x || y } 
Sign up to request clarification or add additional context in comments.

2 Comments

Note that this will fail if a contains falses.
If you don't care about falses, [a, b].transpose.map {|f, s| f || s} works as well :)
5

If you want to replace exactly nil, but not false elements:

a.map.with_index { |e, i| e.nil? ? b[i] : e }
# => [4, 1, 6]

Comments

5

You can use

a.zip(b).map(&:compact).map(&:first) #=> [4, 1, 6]

Steps:

a.zip(b)
#=> [[nil, 4], [1, 5], [nil, 6]]
a.zip(b).map(&:compact)
#=> [[4], [1, 5], [6]]
a.zip(b).map(&:compact).map(&:first)
#=> [4, 1, 6]

By virtue of Array#compact this approach removes nil elements only from the zipped pairs i.e. false elements are not removed.

1 Comment

a.zip(b).map { |e| e.compact[0] } 2 iterations instead of 3 :)
3

Another way is by using a block when creating this new array like so:

a = [nil, 1, nil]
b = [4, 5, 6]
Array.new(a.size) { |i| a[i].nil? ? b[i] : a[i] }
#=> [4, 1, 6]

Comments

0

Still another variant:

a.zip(b).map{|a, b| [*a, *b].first}
# => [4, 1, 6]

This distinguishes nil from false, as expected. But note that you cannot use this with elements that are broken by to_a, such as hashes.

1 Comment

@ndn Yes, you are right. I was thinking about it too.

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.