Reputation: 21
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
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
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.
Upvotes: 1