これは質問に対する答えです: "...文字列をソートしたいが、英数字以外の文字はそのままにしておきたい。"私があなたの例をもっと慎重に読んでから、それがあなたが望んでいたものではないことが分かったのです。私は答えたままにしておきます。なぜなら、質問に答えるからです。
コード
def sort_alphas(str)
alphas, non_alphas = str.each_char.with_index.partition { |c,_| c =~ /[[:alpha:]]/ }
chrs, offsets = alphas.transpose
chrs.sort.zip(offsets).concat(non_alphas).sort_by(&:last).map(&:first).join
end
例
str = "hello, sally! seen 10/dec/2016"
sort_alphas(str)
#=> "acdee, eehll! llno 10/ssy/2016"
説明
次のように例えば文字列の手順です。あなたの答えのための
alphas, non_alphas = str.each_char.with_index.partition { |c,_|
c =~ /[[:alpha:]]/ }
alphas
#=> [["h", 0], ["e", 1], ["l", 2], ["l", 3], ["o", 4], ["s", 7], ["a", 8],
# ["l", 9], ["l", 10], ["y", 11], ["s", 14], ["e", 15], ["e", 16],
# ["n", 17], ["d", 22], ["e", 23], ["c", 24]]
non_alphas
#=> [[",", 5], [" ", 6], ["!", 12], [" ", 13], [" ", 18], ["1", 19], ["0", 20],
# ["/", 21], ["/", 25], ["2", 26], ["0", 27], ["1", 28], ["6", 29]]
chrs, offsets = alphas.transpose
chrs
#=> ["h", "e", "l", "l", "o", "s", "a", "l", "l", "y", "s", "e", "e", "n",
# "d", "e", "c"]
offsets
#=> [0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 16, 17, 22, 23, 24]
sorted_alphas = chrs.sort.zip(offsets)
# => [["a", 0], ["c", 1], ["d", 2], ["e", 3], ["e", 4], ["e", 7], ["e", 8],
# ["h", 9], ["l", 10], ["l", 11], ["l", 14], ["l", 15], ["n", 16],
# ["o", 17], ["s", 22], ["s", 23], ["y", 24]]
sorted_arr = sorted_alphas.concat(non_alphas)
#=> [["a", 0], ["c", 1], ["d", 2], ["e", 3], ["e", 4], ["e", 7], ["e", 8],
# ["h", 9], ["l", 10], ["l", 11], ["l", 14], ["l", 15], ["n", 16], ["o", 17],
# ["s", 22], ["s", 23], ["y", 24], [",", 5], [" ", 6], ["!", 12], [" ", 13],
# [" ", 18], ["1", 19], ["0", 20], ["/", 21], ["/", 25], ["2", 26], ["0", 27],
# ["1", 28], ["6", 29]]
ordered_arr = sorted_arr.sort_by(&:last)
#=> [["a", 0], ["c", 1], ["d", 2], ["e", 3], ["e", 4], [",", 5], [" ", 6],
# ["e", 7], ["e", 8], ["h", 9], ["l", 10], ["l", 11], ["!", 12], [" ", 13],
# ["l", 14], ["l", 15], ["n", 16], ["o", 17], [" ", 18], ["1", 19], ["0", 20],
# ["/", 21], ["s", 22], ["s", 23], ["y", 24], ["/", 25], ["2", 26], ["0", 27],
# ["1", 28], ["6", 29]]
ordered_chrs = ordered_arr.map(&:first)
#=> ["a", "c", "d", "e", "e", ",", " ", "e", "e", "h", "l", "l", "!", " ", "l",
# "l", "n", "o", " ", "1", "0", "/", "s", "s", "y", "/", "2", "0", "1", "6"]
ordered_chrs.join
#=> "acdee, eehll! llno 10/ssy/2016"
ありがとう!それがどういう仕組みで簡単に説明できますか? – Safirah
私は仕事をする前にあなたの答えを読んでいたはずです。 –