文字列がありますが、逆にします。たとえば、文字列を反転するAngularDartフィルターを作成しています。デモンストレーション用ですが、どうやって弦を逆にするのか気になりました。
例:
Hello, world
次のようになります。
dlrow ,olleH
Unicode文字を含む文字列も検討する必要があります。例えば: 'Ame\u{301}lie'
文字列がある場合でも、文字列を逆にする簡単な方法は何ですか?
質問は明確に定義されていません。任意の文字列を逆にすることは意味がなく、出力が壊れることになります。最初の(乗り越えられる)障害は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
...で始めないでください)。
[〜#〜] ascii [〜#〜] Dartの文字列を逆にする1つの方法は次のとおりです。
input.split('').reversed.join('');
注:これは、文字列を逆にするための最速の方法であるとは限りません。代替案については、他の回答を参照してください。
注:これは、すべてのUnicode文字列を適切に処理するわけではありません。
私はいくつかの異なる選択肢のために小さなベンチマークを作成しました:
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)
この機能を試してください
String reverse(String s) {
var chars = s.splitChars();
var len = s.length - 1;
var i = 0;
while (i < len) {
var tmp = chars[i];
chars[i] = chars[len];
chars[len] = tmp;
i++;
len--;
}
return Strings.concatAll(chars);
}
void main() {
var s = "Hello , world";
print(s);
print(reverse(s));
}
(または)
String reverse(String s) {
StringBuffer sb=new StringBuffer();
for(int i=s.length-1;i>=0;i--) {
sb.add(s[i]);
}
return sb.toString();
}
main() {
print(reverse('Hello , world'));
}
この機能をカバーするutilsパッケージがあります。文字列を操作するための優れたメソッドがいくつかあります。
でインストールしてください:
dependencies:
basic_utils: ^1.2.0
使用法 :
String reversed = StringUtils.reverse("helloworld");
Github:
ライブラリ More Dart には、文字列を不変の文字リストのように動作させる軽量のラッパーが含まれています。
import 'package:more/iterable.Dart';
void main() {
print(string('Hello World').reversed.join());
}