How can I rewrite this flatten method without usin

2019-09-23 10:35发布

I am working on building the flatten method in Ruby. Here is my code:

require 'byebug'

class Array
  @@new_array = []
  def new_flatten
    self.each do |element|
      if !element.is_a? Array
        @@new_array << element
      elsif element.is_a? Array
        element.new_flatten
      end
    end
    @@new_array
  end
end

test_array = ([1,2,3,[4,5,6,[7]]])
puts test_array.new_flatten == test_array.flatten

My question is this. Do I need to use the class level variable? I would like to use an instance variable but it doesn't seem to get called when I do:

test_array = []

or

Array.new([])

So I had to create a class-level variable to hold the new flattened array.

标签: ruby
2条回答
做个烂人
2楼-- · 2019-09-23 10:55

The problem with using a class variable is that the same one is visible to all the instances, and new_flatten is an operation for an instance. You should refactor your new_flatten algorithm so it doesn't rely on what is, in effect, a "global" variable for the method calls.

For example, you can use a local variable and Ruby's facility to append arrays with +:

class Array
  def new_flatten
    a = []
    self.each do |element|
      if element.is_a? Array
        a += element.new_flatten
      else
        a << element
      end
    end
    a
  end
end

Also, as some tweaks of style, when doing an if-else, it's often clearer to state the positive logic first. And, you don't need the elsif in this case since the else is the complement of the if. So rather than:

if not something
  do_stuff
elsif opposite_of_not_something
  do_other_stuff
end

It's clearer to say:

if something
  do_stuff
else
  do_other_stuff
end
查看更多
祖国的老花朵
3楼-- · 2019-09-23 10:59

Your question is really confusing. In your title, you talk about calling initialize, but there is no initialize in your code. In your question, you talk about calling an instance variable, but you can't call variables, only methods.

However, implementing flatten is just a simple fold, I don't see the need for storing any intermediate state:

class Array
  def new_flatten
    inject([]) {|acc, el| acc + Array(case el when Array then el.new_flatten else el end) }
  end
end
查看更多
登录 后发表回答