Ruby:如何对字符串进行排序,保留一些字符?

我是Ruby的新手,我想对字符串进行排序,但保留非字母数字字符。 例如: "hello, sally! seen 10/dec/2016" => "ehllo, allsy! eens 01/cde/0126"

我试过了:

 word.scan(/\w+/).collect { |e| ((e.scan /\w/).sort.join)} #=> ["ehllo", "allsy", "eens", "01", "cde", "0126"] 

但我无法弄清楚如何将非字母数字字符放回去。

但我无法弄清楚如何将非字母数字字符放回去。

首先不要删除它们会更容易:

 str = "hello, sally! seen 10/dec/2016" str.gsub(/\w+/) { |m| m.chars.sort.join } #=> "ehllo, allsy! eens 01/cde/0126" 

gsub扫描给定模式的字符串并将每个匹配字符串传递给块,因此使用"hello""sally""seen""10""dec""2016"调用该块。 它通过以下方式排序字符串:

 m = "hello" m.chars #=> ["h", "e", "l", "l", "o"] .sort #=> ["e", "h", "l", "l", "o"] .join #=> "ehllo" 

然后gsub用块的结果替换匹配。

这是对这个问题的回答:“……我想对字符串进行排序,但保留非字母数字字符。” 直到我更仔细地阅读你的例子,我才意识到这不是你想要的。 我会留下我的答案,因为它确实回答了所陈述的问题。

 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"