我有一个字符串,想要将其反转。例如,我正在编写一个AngularDart过滤器,用于反转字符串。这只是演示目的,但它让我想知道如何反转字符串。
示例:
Hello, world
应该变成:
dlrow ,olleH
我也应该考虑带有Unicode字符的字符串。例如:'Ame\u{301}lie'
如果一个字符串包含Unicode字符,那么有什么简单的方法可以翻转它呢?
这个问题的定义不够清晰。翻转任意字符串没有意义,会导致破损的输出。第一个(可克服的)障碍是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码元边界而非rune边界处拆分。
这个问题有一个简单的解决方法:不要翻转单个码元,而是翻转runes:
var input = "Music \u{1d11e} for the win"; // Music for the win
print(new String.fromCharCodes(input.runes.toList().reversed)); // niw eht rof cisuM
但这还不是全部。符文也可以有特定的顺序。这第二个障碍要解决起来困难得多。一个简单的例子:
But that's not all. Runes, too, can have a specific order. This second obstacle is much harder to solve. A simple example:
var input = 'Ame\u{301}lie'; // Amélie
print(new String.fromCharCodes(input.runes.toList().reversed)); // eiĺemA
请注意,重音落在错误的字符上。
可能有其他语言更加敏感于单个符文的顺序。
如果输入有严格的限制(例如Ascii或Iso Latin 1),则技术上可以反转字符串。然而,我还没有看到过一个单一用例,这种操作是有意义的。
将此问题用作展示字符串具有类似列表的操作不是一个好主意。除了少数用例外,必须针对特定语言进行处理字符串,并使用具有语言特定知识的高度复杂的方法。
特别是以英语为母语的人必须注意:几乎不能将字符串处理为单个字符的列表。在几乎所有其他语言中,这将导致程序出错。(而且不要让我开始讨论 toLowerCase 和 toUpperCase ...)。
toLowerCase
和 toUpperCase
到底有什么问题。 - AndrétoLowerCase
,例如 \u{1d11e}
。 - Michel Feinsteinpackage:characters
,它允许您在字形簇级别上操作字符串,这正是您需要的,以避免打断重音和它们的字符,或更改复杂的表情符号,甚至只是将"\r\n"
转换为\n\r"
。使用characters包,您可以执行string.characters.toList().reversed.join("")
而不会弄乱组合字符。即使您正确地执行了反转字符串,我仍然没有找到任何实际需要反转字符串的情况。如果""
不变成""
,那么它是否真正正确呢? - lrn这是在Dart中反转一个ASCII字符串的一种方法:
input.split('').reversed.join('');
注意:这并不一定是最快反转字符串的方法。有其他方案可以参考。
注意:这种方法不能正确处理所有Unicode字符串。
print('Ame\u{301}lie'.split('').reversed.join(''));
==> eiĺemA
- Seth Ladd我为几个不同的替代方案做了一个小基准测试:
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)
库更多Dart包含一个轻量级的字符串包装器,使它们表现得像一个不可变的字符列表:
import 'package:more/iterable.dart';
void main() {
print(string('Hello World').reversed.join());
}
试试这个函数
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'));
}
有一个工具包涵盖了这个功能。它还有一些更好的方法来操作字符串。
安装它:
dependencies:
basic_utils: ^1.2.0
使用方法:
String reversed = StringUtils.reverse("helloworld");
反转"Hello World"
Characters
的Dart软件包从给定字符串中提取字符。然后我们可以将它们反转并重新连接以生成反转后的字符串。String reverse(String string) {
if (string.length < 2) {
return string;
}
final characters = Characters(string);
return characters.toList().reversed.join();
}
创建此扩展:
extension Ex on String {
String get reverse => split('').reversed.join();
}
使用方法:
void main() {
String string = 'Hello World';
print(string.reverse); // dlroW olleH
}
** 这里有一个可以用来反转字符串的函数。它接受一个字符串作为输入,并使用名为split()的dart包从给定的字符串中提取字符。然后我们可以将它们反转并重新连接以生成反转后的字符串。 **
String? stringReverse(String? string) {
if (string != null) {
final output = string.split('').reversed.join();
return output;
}
}
void main() {
String? string = stdin.readLineSync();
print(stringReverse(string));
}
'Ame\u{301}lie'
。 - Florian Loitsch