以前に next_permutation のアルゴリズムを勉強していた際、配列の一部分だけを逆順に並べ替える操作が(メソッド一発では)できないことが気になった。 C++ の std::reverse
であれば、列の始端と終端を指定するので部分的にもできそう。
メソッドが無いなら作っておけばいいか、ということで作ってみた。
実装に使うメソッドは範囲指定可能な #[]
と #[]=
のみなので、配列だけでなく文字列にも適用できる。複数のクラスを拡張するならモジュール化しておくと良さそう。
# Array と String に共通のメソッドを使って実装
module SequenceExtension
# 破壊的メソッド
# ※ #[] が列を返さないような引数は考慮していない
def reverse_in_range!(*args)
self[*args] = self[*args].reverse!
self
end
# おまけ:非破壊的メソッド
def reverse_in_range(*args)
self.dup.reverse_in_range!(*args)
end
end
# include なり refinement なりで追加
Array.include(SequenceExtension)
using Module.new { refine(String) { import_methods SequenceExtension } }
ary = [0, 1, 2, 3, 4]
p ary.reverse_in_range(1, 3) #=> [0, 3, 2, 1, 4]
ary.reverse_in_range!(2..-1); p ary #=> [0, 1, 4, 3, 2]
str = "abcd-xyz"
str.reverse_in_range!(/\w+/); p str #=> "dcba-xyz"