Re: 文字列"0123456789"を"9876543210"に変換する方法

[Javascript] 文字列"0123456789"を"9876543210"に変換する方法 たまには呪文をとなえてみるか:仕事版/ウェブリブログ
逆にするならreverseの方が自然かなあ?(Javascript正規表現の話という前提を壊してしまいますが)

>>> "0123456789".split('').reverse().join('')
"9876543210"

JavaScriptは文字列にreverseできないので一旦配列にしてから逆転・結合します。
splitに空の正規表現(または文字列)を渡すと一文字ずつに分解した配列を返してくれます。(無理やり正規表現の話にしてみた)

>>> "0123456789"
"0123456789"
>>> "0123456789".split('')
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
>>> "0123456789".split('').reverse()
["9", "8", "7", "6", "5", "4", "3", "2", "1", "0"]
>>> "0123456789".split('').reverse().join('')
"9876543210"


ところでPerl

% perl -e 'print scalar reverse "0123456789"'
9876543210

と直接文字列をreverseできます。簡単ですね。
ちょっとはまったのが、reverseがリストコンテキストで呼ばれるとリストの逆転を行なうところ。
リストコンテキストだと("0123456789")というリストを逆転した("0123456789")というリストが返ってきてしまうので、scalar演算子スカラーコンテキストで呼び出しています。一旦スカラー変数に突っ込むならscalarいらないけど。

% perl -e 'my $x = reverse "0123456789"; print $x'
9876543210


ちょっと試してみたんだけれど、やっぱりIEではfunction内部ではRegExp.$1が定義されていない模様。
このため、キャプチャした文字列を相手に何かという事はできないみたい。

a.replace(new RegExp("(\\d)","g"),
  function() {
    return String(Math.abs(parseInt(arguments[1]) - 9));
  }
);

でいいんじゃないかな。マッチした部分文字列はreplace-functionの引数として渡ってきます。ちなみに0番目はマッチした部分全体で、1番目以降がグループマッチした部分文字列です。

a.replace(new RegExp("(\\d)","g"),
  function($0, $1) {
    return String(Math.abs(parseInt($1) - 9));
  }
);

のように明示的に仮引数に代入してもいいです。(「仮引数に代入」って言い回し久しぶりに聞いたな・・・)



replace-function内のRegExp.$nは確かにIEで変な動きしますね。
/REGEXP/g(グローバルマッチ)の場合、全てのマッチが完了するまで更新されないんだと思います。