0

I have a list of posts ordered by most recent date of modification. I want to stagger them into two columns to have the two recent modified posts at the top. This code is fairly self explanatory:

posts.each do |post|
  right_column << post if shift
  left_column << post if !shift
  shift = shift ? false : true
end

posts = left_column + right_column

For example, given the input  [1, 2, 3, 4], the goal is to produce [1, 3, 2, 4].

Is there a more elegant/idiomatic way to achieve this in Ruby?

5
  • 2
    rather you could give some examples..input and expected output.. Commented Aug 3, 2013 at 16:27
  • @Babai added a simple example. Commented Aug 3, 2013 at 16:52
  • that imperative style is terribly unidiomatic, search for ruby+functional+programming. Commented Aug 3, 2013 at 18:17
  • @tokland That's exactly why I am asking for a more idiomatic way to do it... Commented Aug 3, 2013 at 19:00
  • @louism: Of course! My point was that a particular solution fot this problem won't help much, you need to be aware of the functional principles as a whole. Hope that helps: code.google.com/p/tokland/wiki/RubyFunctionalProgramming Commented Aug 3, 2013 at 19:51

2 Answers 2

4

Use each_slice to get the rows, then transpose it into columns, then flatten them:

posts = (1..10).to_a  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

posts.each_slice(2).to_a.transpose.flatten
#=> [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]

Or, to get the left and right columns separately:

left, right = posts.each_slice(2).to_a.transpose
Sign up to request clarification or add additional context in comments.

2 Comments

Why stop there when posts = posts.each_slice(2).to_a.transpose.flatten does the whole job?
@Borodin Because when I answered the question there was no sample input/output :). Updated now, though.
1

Update

I have noticed that you need left_column and right_column only as temporary variables.

You may prefer this

posts = %W{ A B C D E F G H I J}

indices = posts.each_index.partition(&:even?).flatten
posts = posts.values_at(*indices)

p posts

output

["A", "C", "E", "G", "I", "B", "D", "F", "H", "J"]

If you use each_with_index you can push to different arrays depending on whether the index is even or odd

posts.each_with_index do |post, i|
  (i.even? ? left_column : right_column) << post
end

2 Comments

Using each_index & partition is creative, +1.
@tokland: Just swap partition for group_by{|i| i % 3}.values

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.