开发者

rarefying array with limit

I have array of objects form AR I want to rarefy them, with limit.

Current method looks like:

  def rarefied_values(limit = 200)
    all_values = self.values.all
    rarefied_values = []

    chunk_size = (all_values.size / limit.to_f).ceil
    if all_values.size > limit
开发者_开发百科      all_values.each_slice(chunk_size) do |chunk|
        rarefied_values.push(chunk.first)
      end
      return rarefied_values
    else
      return all_values
    end
  end

Any hints for refactoring?


def rarefied_values(limit = 200)
  all_values = values.all
  return all_values unless all_values.size > limit
  chunk_size = all_values.size / limit
  (0...limit).map{|i| all_values[i*chunk_size]}
end

Some general points in refactoring in ruby

  • self can be omitted usually. In a few cases, you cannot, for example self.class. In this case, self.values.all => values.all
  • If one of the conditioned procedures is much simpler compared to the others, then place that simple case first, and get rid of it from the rest of the code using return. In this case, return all_values unless all_values.size > limit
  • In general, when you need nested conditions, design it so that cases with simpler procedures split off eariler, and the complicated cases are placed toward the end.
  • Let the code be lazy as possible. In this case, rarefied_values = [] is not necessary if all_values.size > limit. So put that in the conditioned section.


Here's a naïve refactor, keeping your same methods, but removing the explicit return calls and only performing certain transformations if necessary:

def rarefied_values(limit = 200)
  all_values = self.values.all
  if all_values.size <= limit
    all_values
  else
    chunk_size = (all_values.size / limit.to_f).ceil
    [].tap{ |rare| all_values.each_slice(chunk_size){ |c| rare << c.first } }
  end
end

Here's a faster, more terse version:

def rarefied_values(limit = 200)
  all_values = self.values.all      
  if (size = all_values.size) <= limit
    all_values
  else
    all_values.values_at(*0.step(size-1,(size.to_f/limit).ceil))
  end
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜