0

Given I have the following array:

operations = [
  [
    :do_this,
    ["a"]
  ],
  [
    :do_that,
    ["b", "c"]
  ],
  [
    :then_this,
    ["b"]
  ]
]

How do I transform above so it looks like:

DoThisOperation.new(DoThatOperation.new(ThenThisOperation.new('b'), 'b' , 'c'), 'a')

This is as far as I've gotten:

require 'active_support/inflector'

class DoThisOperation
  def initialize(successor = nil, a)
  end
end

class DoThatOperation
  def initialize(successor = nil, b, c)
  end
end

class ThenThisOperation
  def initialize(successor = nil, b)
  end
end

operations = [
  [
    :do_this,
    ["a"]
  ],x
  [
    :do_that,
    ["b", "c"]
  ],
  [
    :then_this,
    ["b"]
  ]
]

operations.reverse.reduce do |result, element|
  klass_name = element[0].to_s.camelize
  args = element[1]
  "#{klass_name}Operation".constantize.new(result, *args)
end

Is reduce/inject the right way to go about this? If so, what should I be doing above?

3
  • The reduce code should be: operations.reverse.reduce(nil) do |result, element| ..., you miss nil as initial value. By the way, your require that ThenThisOperation map with a, it shoule be map with b, right ? Or that is what you want, the params will be in inverse order ? Commented Apr 15, 2021 at 3:50
  • @muistooshort You are right. Let me make an edit on the expectation Commented Apr 15, 2021 at 7:16
  • @LamPhan You are right. With nil (i.e. reduce(nil)), it works as expected! Thank you for that. If you leave it as an answer, I will gladly mark it as such Commented Apr 15, 2021 at 7:23

1 Answer 1

2

Is reduce/inject the right way to go about this?

Yes, but you need to pass an initial value to reduce, e.g. nil. Otherwise, the first element (in your case the last element) will be used as the initial value without being converted.

This would work:

operations.reverse.reduce(nil) do |result, element|
  klass_name = element[0].to_s.camelize
  args = element[1]
  "#{klass_name}Operation".constantize.new(result, *args)
end

You can further simplify it by using array decomposition:

operations.reverse.reduce(nil) do |result, (name, args)|
  klass_name = name.to_s.camelize
  "#{klass_name}Operation".constantize.new(result, *args)
end

Or even:

operations.reverse.reduce(nil) do |result, (name, args)|
  "#{name}_operation".camelize.constantize.new(result, *args)
end
Sign up to request clarification or add additional context in comments.

1 Comment

Very nice tip on the array decomposition part

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.