40

私は文字列を持っています。それを逆にしたいと思います。たとえば、文字列を逆にする AngularDart フィルターを作成しています。これは単なるデモンストレーション用ですが、文字列を逆にする方法を考えさせられました。

例:

Hello, world

次のようになります。

dlrow ,olleH

Unicode 文字を含む文字列も考慮する必要があります。例えば:'Ame\u{301}lie'

文字列を逆にする簡単な方法は何ですか?

4

9 に答える 9

83

質問がうまく定義されていません。任意の文字列を逆にすることは意味がなく、出力が壊れる可能性があります。最初の (克服可能な) 障害は Utf-16 です。Dart 文字列は Utf-16 としてエンコードされ、コード単位だけを逆にすると無効な文字列になります。

var input = "Music \u{1d11e} for the win"; // Music  for the win
print(input.split('').reversed.join()); // niw eht rof

関数はsplit、この問題に対して明示的に警告します (例を示します)。

空の文字列パターン ('') で分割すると、ルーン境界ではなく、UTF-16 コード単位の境界で分割されます[.]

これには簡単な修正があります: 個々のコード単位を逆にする代わりに、ルーンを逆にすることができます:

var input = "Music \u{1d11e} for the win"; // Music  for the win
print(new String.fromCharCodes(input.runes.toList().reversed)); // niw eht rof  cisuM

しかし、それだけではありません。ルーンも特定の順序を持​​つことができます。この 2 番目の障害は、解決するのがはるかに困難です。簡単な例:

var input =  'Ame\u{301}lie'; // Amélie
print(new String.fromCharCodes(input.runes.toList().reversed)); // eiĺemA

アクセントが間違った文字にあることに注意してください。

個々のルーン文字の順序にさらに敏感な言語はおそらく他にもあるでしょう。

入力に厳しい制限がある場合 (たとえば、Ascii や Iso Latin 1 など)、文字列を逆にすることは技術的に可能です。ただし、この操作が理にかなっているユースケースはまだ 1 つも見たことがありません。

文字列にリストのような操作があることを示す例としてこの質問を使用することもお勧めできません。いくつかのユースケースを除いて、文字列は特定の言語に関して、また言語固有の知識を持つ非常に複雑なメソッドで処理する必要があります。

特に、英語を母国語とする人は注意を払う必要があります。文字列が単一文字のリストであるかのように処理されることはめったにありません。他のほとんどすべての言語では、これはバグのあるプログラムにつながります。(そして、私を始めさせないでくださいtoLowerCase... toUpperCase)。

于 2014-02-06T20:46:37.480 に答える
18

DartでASCII文字列を逆にする 1 つの方法を次に示します。

input.split('').reversed.join('');
  1. すべての文字で文字列を分割し、リストを作成します
  2. リストを反転する反復子を生成する
  3. リストに参加する (新しい文字列を作成する)

注: これは必ずしも文字列を逆にする最速の方法ではありません。代替案については、他の回答を参照してください。

注: これは、すべての Unicode 文字列を適切に処理するわけではありません。

于 2014-02-03T07:18:35.167 に答える
9

いくつかの異なる代替案の小さなベンチマークを作成しました。

String reverse0(String s) {
  return s.split('').reversed.join('');
}

String reverse1(String s) {
  var sb = new StringBuffer();
  for(var i = s.length - 1; i >= 0; --i) {
    sb.write(s[i]);
  }
  return sb.toString();
}

String reverse2(String s) {
  return new String.fromCharCodes(s.codeUnits.reversed);
}

String reverse3(String s) {
  var sb = new StringBuffer();
  for(var i = s.length - 1; i >= 0; --i) {
    sb.writeCharCode(s.codeUnitAt(i));
  }
  return sb.toString();
}

String reverse4(String s) {
  var sb = new StringBuffer();

  var i = s.length - 1;

  while (i >= 3) {
    sb.writeCharCode(s.codeUnitAt(i-0));
    sb.writeCharCode(s.codeUnitAt(i-1));
    sb.writeCharCode(s.codeUnitAt(i-2));
    sb.writeCharCode(s.codeUnitAt(i-3));
    i -= 4;
  }

  while (i >= 0) {
    sb.writeCharCode(s.codeUnitAt(i));
    i -= 1;
  }

  return sb.toString();
}

String reverse5(String s) {
  var length = s.length;
  var charCodes = new List(length);
  for(var index = 0; index < length; index++) {
    charCodes[index] = s.codeUnitAt(length - index - 1);
  }

  return new String.fromCharCodes(charCodes);
}
main() {
  var s = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";

  time('reverse0', () => reverse0(s));
  time('reverse1', () => reverse1(s));
  time('reverse2', () => reverse2(s));
  time('reverse3', () => reverse3(s));
  time('reverse4', () => reverse4(s));
  time('reverse5', () => reverse5(s));
}

結果は次のとおりです。

reverse0: => 331,394 ops/sec (3 us) stdev(0.01363)
reverse1: => 346,822 ops/sec (3 us) stdev(0.00885)
reverse2: => 490,821 ops/sec (2 us) stdev(0.0338)
reverse3: => 873,636 ops/sec (1 us) stdev(0.03972)
reverse4: => 893,953 ops/sec (1 us) stdev(0.04089)
reverse5: => 2,624,282 ops/sec (0 us) stdev(0.11828)
于 2014-02-03T18:53:12.840 に答える