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.

Saleh Enam Shohag
  • 1,039
  • 1
  • 12
  • 23
  • 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. – sawa Dec 10 '13 at 09:00
  • It is not, @sawa. The question maker appears to want things ordered as if they where months of a given year. – paradoja Dec 10 '13 at 09:17
  • 1
    is `"50/2013"` a mistake or does the `50` mean week of the year? – benjaminjosephw Dec 10 '13 at 09:20
  • 1
    Thanks, @benjaminjosephw it means the week of the year – Saleh Enam Shohag Dec 10 '13 at 09:27
  • @paradoja That could not be the case. There is no month `50`. You are absolutely wrong. – sawa Dec 10 '13 at 10:09
  • @SalehEnamShohag All this mess, including misinterpretation of your question in an answer is due to you not describing the question enough. You only mentioned "sort", and nothing else. That would mean "sort as a string". You did not mentioned that it should be sorted as integers, or each item be converted to an array. It is all your fault. – sawa Dec 10 '13 at 10:13

2 Answers2

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]
#]
Santhosh
  • 28,097
  • 9
  • 82
  • 87
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.

jvnill
  • 29,479
  • 4
  • 83
  • 86