arr = [
"Target 4", "Goal C", "Target 11", "Target 13", "Goal B", "Target 3",
"Target 1", "Target 2", "Target 12", "Target 20", "Target 21",
"Target 10", "Goal A", "Dog D", "Cat 5"
]
arr.sort_by do |s|
t = s[/\S+\z/]
Integer(t, exception: false) ? [1, t.to_i] : [0, t]
end
#=> ["Goal A", "Goal B", "Goal C", "Dog D", "Target 1", "Target 2",
# "Target 3", "Target 4", "Cat 5", "Target 10", "Target 11",
# "Target 12", "Target 13", "Target 20", "Target 21"]
My additions of "Dog D" and "Cat 5" were to illustrate my assumption of how the sort was to be performed; that is, on the end of the string only.
See Kernel#Integer.
Items are compared using Array#<=>. See especially the third paragraph of that doc. Thus, the first element of the array returned by Enumerable#sort_by ensures that in the sorted array strings ending in a string of digits appear after those that do not. The second element of the array returned by sort_by breaks the ties.
The regular expression /\S+\z/ is read, "Match one or more (+) non-whitespace characters (\S) followed by the end of the string (\z)". When s = "Target 12", for example, t = s[/\S+\z/] #=> "12". See the fourth form of String#[] at that link.
For a different sorting assumption (which should be obvious for the example array, before and after it is sorted) we could write:
arr = [
"Target 4", "XGoal C", "ATarget 11", "Target 13", "Goal B", "Target 3",
"Target 1", "Target 2", "Target 12", "ATarget 20", "Target 21",
"ATarget 10", "XGoal A"
]
arr.sort_by do |s|
b, e = s.split
Integer(e, exception: false) ? [1, b, e.to_i] : [0, b, e]
end
#=> ["Goal B", "XGoal A", "XGoal C", "ATarget 10", "ATarget 11",
# "ATarget 20", "Target 1", "Target 2", "Target 3", "Target 4",
# "Target 12", "Target 13", "Target 21"]
"Dog woof"and"Cat 5"? If so, what would be the desired sorted array? In future I suggest you reduce the size of your example to the minimum required to make the point. There is no need, for example, for so many"Target X"'s.'sortaccepts a block which, for two arguments, decides which argument comes first in the sorting order. Basically this is what defines the sorting logic. I would first split the words into two parts, and based on which define what comes first. Only you know the algorithm, because from your description, I don't understand how i.e.['Goal A', 'Goal 06', 'Goal B', 'Goal 4', 'Goal 4x']is to be sorted.