Fabienne
Fabienne

Reputation: 21

Sort an array of array by 2 conditions

I have to sort this

ary = [[5, "e", "2"], [2, "r", "="], [2, "y", "2"], [2, "h", "="]]

to obtain :

# => [[5, "e", "2"], [2, "y", "2"], [2, "h", "="], [2, "r", "="]] 

If the last element (index 2) is equal to "=" it must be after the array which has the same first element even if the letter is before. Something like this :

ary.each_with_index do |array, index|
  if ary[index][2] == "=" && ary[index][0] == ary[index +1][2]
    a = ary[index]
    b = ary[index +1]
    ary[index] = b
    ary[index+1] = a
  end
end

Upvotes: 2

Views: 58

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110685

I assume that, for elements ending with "=", sorting is by decreasing value of the first element (integers) and when there are ties, by increasing order of the second element (strings). Further, I assume sorting is the same for elements not ending with "=", except when the first two elements both tie, sorting is by increasing order of the last element (strings).

def sort_em(arr)
  arr.sort_by { |n, s1, s2| [s2 == "=" ? 1 : 0, -n, s1, s2] }
end

sort_em [[5, "e", "2"], [2, "r", "="], [2, "y", "2"], [2, "h", "="]]
  #=> [[5, "e", "2"], [2, "y", "2"], [2, "h", "="], [2, "r", "="]]

See the third paragraph of the doc for Array#<=> for an explanation of how arrays are ordered when sorting.

To ensure elements ending with "=" come last in the sort, I've simply added 1 (0) at the beginning of array in sort_by's block for arrays ending (not ending) with "=".

Upvotes: 2

ulferts
ulferts

Reputation: 2242

You can use sort and provide your own block for sorting:

ary.sort do |a, b| 
  if a[2] == '=' && b[2] != '='
    # a has '=' => a > b 
    1
  elsif b[2] == '=' && a[2] != '='
    # b has '=' => a < b 
    -1
  else
    # This is hit if neither a nor b have a '=' OR when both do.
    # Use default comparison operator
    # but restrict it to the second element of the array
    a[1] <=> b[1]
  end
end

The block needs to return a value that is 1, -1 or 0. Based on this, the values are placed in order.

  • 1: a > b
  • -1: a < b
  • 0: a = b

Upvotes: 1

Related Questions