4

I have a two dimensional array which has following structure

a = [["5/2013", 20.0, 6.0, 6.0], 
["7/2013", 73.0, 66.0, 66.0], 
["50/2013", 11530.0, 12625.27, 12087.75], 
["2/2014", 5926.0, 6058.0, 5876.4], 
["3/2013", 15.0, 0.0, 0.0], 
["4/2013", 15.0, 0.0, 0.0]]

I want to sort the array based on first element, first element of each array presents the week no in year(i.e. "2/2014" means 2nd week in 2014, which is greater than "50/2013") the result will be like this

["3/2013", 15.0, 0.0, 0.0], 
["4/2013", 15.0, 0.0, 0.0],
["5/2013", 20.0, 6.0, 6.0], 
["7/2013", 73.0, 66.0, 66.0], 
["50/2013", 11530.0, 12625.27, 12087.75], 
["2/2014", 5926.0, 6058.0, 5876.4], 
]

I tried with this one

a.sort{|a,b| a[0].split('/')[1].to_i <=> b[0].split('/')[1].to_i  && a[0].split('/')  [0].to_i <=> b[0].split('/')[0].to_i}

but it does not help. I am new in ruby and rails. Can anyone please help me to solve my problem.

6
  • If you sort as is, "2/2014" should come first and "7/2013" should come last, unlike what you have (dismissing the fact that your expected output is not a valid Ruby expression at all). Your question as is is contradictory. Commented Dec 10, 2013 at 9:00
  • It is not, @sawa. The question maker appears to want things ordered as if they where months of a given year. Commented Dec 10, 2013 at 9:17
  • 1
    is "50/2013" a mistake or does the 50 mean week of the year? Commented Dec 10, 2013 at 9:20
  • 1
    Thanks, @benjaminjosephw it means the week of the year Commented Dec 10, 2013 at 9:27
  • @paradoja That could not be the case. There is no month 50. You are absolutely wrong. Commented Dec 10, 2013 at 10:09

2 Answers 2

10
a.sort_by {|i| i.first.split('/').map(&:to_i).reverse }

#[
#  ["3/2013", 15.0, 0.0, 0.0],
#  ["4/2013", 15.0, 0.0, 0.0],
#  ["5/2013", 20.0, 6.0, 6.0],
#  ["7/2013", 73.0, 66.0, 66.0],
#  ["50/2013", 11530.0, 12625.27, 12087.75],
#  ["2/2014", 5926.0, 6058.0, 5876.4]
#]
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. It is exactly the answer i was looking
Pretty cool, but what's the exact meaning of &:to_i in the map method?
@LeoHuang &:to_i is a shortcut for { |x| x.to_i }. This will give you more insight stackoverflow.com/questions/1217088/…
2

Assuming you have a properly formed first element, meaning Date.parse will not raise any exception, use the following

>> array = [["5/2013", 20.0, 6.0, 6.0], ["7/2013", 73.0, 66.0, 66.0], ["50/2013", 11530.0, 12625.27, 12087.75], ["2/2014", 5926.0, 6058.0, 5876.4], ["3/2013", 15.0, 0.0, 0.0], ["4/2013", 15.0, 0.0, 0.0]]
>> array.sort_by { |date, _| Date.parse(date) }

To handle improperly formed date like 50/2013 (in your question), you need to decide the default value. Say you want to set the default value to today's date, change the second line to

>> array.sort_by { |date, _| Date.parse(date) rescue Date.today}

EDIT

I assumed that the first element is like a date. Looking at your question a second time leads me to believe that it isn't a date. If this isn't a date, I'll have to agree with sawa's comment. If you really want to sort this though, use the following

array.sort do |a,b|
  num1, year1 = a[0].split('/')
  num2, year2 = b[0].split('/')

  if year1 == year2
    num1.to_i <=> num2.to_i
  else
    year1.to_i <=> year2.to_i
  end
end

EDIT ignore the big method above, use Santosh's answer.

1 Comment

Thanks. Actually by 50/2013 i mean week of the year

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.