1

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). (*Edit: I meant the larger of the two numbers, which is why this array doesn't match below answer, so I used that answer below but used .max instead of .min )

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!

3
  • 1. Are a, b and x always the same length? 2. Can a contain any nil elements? 3. Do you want the arrays produced by "Step One" and "Step Two", or just the one produced by "Step 3", considering that the "Step 3" array could be constructed without first constructing the other two arrays. Commented Nov 14, 2016 at 3:42
  • 4. Can b contain integers as well as nil and an array containing a hash? Commented Nov 14, 2016 at 3:51
  • 1. yes 2. I don't think so, it's from a json I'm still exploring and haven't come across any yet. 3. tbh, I really only need step 3, so thank you for your answer below! 4. b will only contain nil or an array containing a hash as displayed. great follow-up questions, thank you for your excellent answer below! Commented Nov 14, 2016 at 6:09

2 Answers 2

6
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 bb and the return value were needed, you might perform the following calculation.

[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]
Sign up to request clarification or add additional context in comments.

5 Comments

I would prefer to do step 1, THEN get the result in Step 3, so would you remind re-writing that second code using bb instead of b? Thank you!
iamse7en I made the change you requested.
Thank you, this is working perfectly! I have one more criteria to add if you don't mind! I think you'll be able to solve it in less than a minute. gist.github.com/anonymous/15bd06c052dbbccab84789503fcab337 I would greatly appreciate it. Feel free to add the answer above or in the gist.
tried this on my own, not pretty but gets the work done. b.each.with_index { |e, i| if e.nil? && x[i].nil?; b.delete_at(i); p.delete_at(i) ;a.delete_at(i); x.delete_at(i); end }
Would inserting ``reject { |ae,bbe,xe| ae.nil? && xe.nil? }.` between transpose and map achieve your objective?
2

Step 1.

b.map!{ |x| x.first.values.first if x }

Step 2.

c = a.map.each_with_index{ |x, i| (x && b[i]) ?  ((x || 0) + (b[i] || 0))/2 : (x || b[i]) }

Step 3.

c.map.each_with_index{ |k, i| (k && x[i]) ? [k, x[i]].max : (k || x[i])  } 

Comments

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.