iamse7en - 1 year ago 69
Ruby Question

# Ruby: Comparing arrays and creating new ones based on specific conditions

I have 3 arrays of equal length. Some spots are nil, which complicates things, but I need to retain their order.

``````a = [5.2, 3.0, 1.21, 7.0, 5.0, 5.0, 6.0, 8.0, 10.0, 10.0]
b = [nil, nil, [{"price"=>1.99, "size"=>269.897475661239}], nil, nil, nil, nil, nil, nil, nil]
x = [6.0, 6.2, 2.5, 5.0, 9.0, 2.36, 15.5, 20.0, nil, nil]
``````

(Step One, I want to iterate over b so that
`b = [nil, nil, 1.99, nil, nil, nil, nil, nil, nil, nil]`
. Just need ["price"], ignore ["size"]. Couldn't figure that out.)

Step Two, I want to create a new array (
`c`
) that averages
`a`
and
`b`
but where there is nil, just take the one that has a value. In other words,
`c`
would
`= [5.2, 3.0, 1.6, 7.0, 5.0, 5.0, 6.0, 8.0, 10.0, 10.0]`
which looks like
`a`
except the third spot the average of 1.21 and 1.99 (1.6).

So I have my original third array
`x = [6.0, 6.2, 2.5, 5.0, 9.0, 2.36, 15.5, 20.0, nil, nil]`
. Step Three, I want to compare
`c`
and
`x`
to and create a new array
`z`
that takes the SMALLER of the two numbers, or if nil, the one that has a value.
`z`
is the result I would like.

Thus
`z`
should
`= [6.0, 6.2, 2.5, 7.0, 9.0, 5.0, 15.5, 20.0, 10.0, 10.0]`
(if my eyes are correct).

I know those steps are tedious, but I need to go in that order because I have lots of arrays where I need to average 2 then compare with a third and take the larger number and with random nil values laced throughout, it gets beyond my abilities. Can't figure it out, and would greatly appreciate some help! Thank you!

``````bb = b.map { |e| e.is_a?(Array) ? e.first["price"] : e }
#=> [nil, nil, 1.99, nil, nil, nil, nil, nil, nil, nil]

c = a.zip(bb).map { |ea, ebb| ebb.nil? ? ea : (ea+ebb)/2.0 }
#=> [5.2, 3.0, 1.6, 7.0, 5.0, 5.0, 6.0, 8.0, 10.0, 10.0]

c.zip(x).map { |cc,xx| xx.nil? ? cc : [cc,xx].min }
#=> [5.2, 3.0, 1.6, 5.0, 5.0, 2.36, 6.0, 8.0, 10.0, 10.0]
``````

If only the last array is needed, you might first compute `bb` above, then perform the following calculaton.

``````[a,bb,x].transpose.map do |ae,bbe,xe|
ab_avg = bbe ? (ae+bbe)/2.0 : ae
xe ? [ab_avg, xe].min : ab_avg
end
#=> [5.2, 3.0, 1.6, 5.0, 5.0, 2.36, 6.0, 8.0, 10.0, 10.0]
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download