0
\$\begingroup\$

My model called Customer contains a method called generate_fields which creates records based on its return values.

def generate_fields
  words.map do |word|
    numbers.map do |number|
      content = find_content(word, number)
      next if content.nil?

      {
        kind: word,
        value: content
      }
    end.compact
  end.flatten
end

#[
#  { kind: "S", value: "BRL" },
#  { kind: "M", value: "AUS" },
#  { kind: "L", value: "PER" },
#]

The methods words and numbers are private and return an array of strings. Their implementation is not relevant to this discussion. generate_fields returns an array of hashes which is used to create multiple customers at the database.

Customer.create(generate_fields)

The problem is compact and flatten create a new array for every time they are called as pointed out by @David Aldridge. How can this function be rewritten to avoid excessive array creation? Thanks in advance.

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to Code Review. As you have currently framed the question, you seem to be asking about a specific practice, with two hypothetical code snippets included merely as an example. To make this question on-topic, please state what task the code accomplishes, and retitle the question accordingly, so that we are reviewing real concrete code from a project. See How to Ask. \$\endgroup\$ – 200_success Mar 30 at 4:55
  • \$\begingroup\$ @200_success thanks for pointing me out in the right direction. I've changed the question and I believe now it's closer to this community guidelines. \$\endgroup\$ – tmmgarcia Mar 30 at 21:48
1
\$\begingroup\$

I'm not a fan of the latter because the compact and flatten methods create new arrays.

Here's another variation with two additional style options: use of product to combine the two arrays, and each_with_object:

def generate_fields_3
  words   = ["foo", "bar", "bla"]
  numbers = [1, 2, 3]

  words.product(numbers).each_with_object([]) do |(word, number), fields|
    content = find_content(word, number)
    next if content.nil?

    fields << {
      kind: word,
      value: content
    }
  end
end
\$\endgroup\$
  • \$\begingroup\$ I should point out that if efficiency is the aim then the product method should be avoided really. For two arrays size N and M it creates another (N*M)+1 arrays. \$\endgroup\$ – David Aldridge Mar 31 at 10:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.