如何在 Dart 中反转字符串?

问题描述 投票:0回答:11

我有一个字符串,我想反转它。例如,我正在编写一个反转字符串的 AngularDart 过滤器。这只是为了演示目的,但它让我想知道如何反转字符串。

示例:

Hello, world

应该变成:

dlrow ,olleH

我还应该考虑带有 Unicode 字符的字符串。例如:

'Ame\u{301}lie'

即使有,有什么简单的方法可以反转字符串?

string flutter dart split reverse
11个回答
103
投票

这个问题没有明确定义。反转任意字符串没有意义,并且会导致输出损坏。第一个(可克服的)障碍是 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

但这还不是全部。符文也可以有特定的顺序。第二个障碍更难解决。一个简单的例子:

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

请注意,重音符号位于错误的字符上。

可能还有其他语言对单个符文的顺序更加敏感。

如果输入有严格的限制(例如 Ascii 或 Iso Latin 1),那么在技术上可以反转字符串。但是,我还没有看到任何一个使用此操作有意义的用例。

使用这个问题作为例子来展示字符串具有类似列表的操作也不是一个好主意。除了少数用例之外,字符串必须根据特定语言进行处理,并使用具有特定语言知识的高度复杂的方法。

特别是以英语为母语的人必须注意:字符串很少可以像单个字符列表一样进行处理。在几乎所有其他语言中,这都会导致有错误的程序。 (别让我开始说

toLowerCase
toUpperCase
...)。


24
投票

这是在 Dart 中反转 ASCII 字符串的一种方法:

input.split('').reversed.join('');
  1. 将字符串拆分为每个字符,创建一个列表
  2. 生成一个反转列表的迭代器
  3. 加入列表(创建新字符串)

注意:这不一定是反转字符串的最快方法。请参阅其他答案以获取替代方案。

注意:这不能正确处理所有 unicode 字符串。


14
投票

我为几种不同的替代方案制定了一个小基准:

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)

2
投票

试试这个功能

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'));
}

2
投票

More Dart 包含一个轻量级的字符串包装器,使它们的行为就像一个不可变的字符列表:

import 'package:more/iterable.dart';

void main() {
  print(string('Hello World').reversed.join());
}

1
投票

有一个utils包涵盖了这个功能。它有一些更好的字符串操作方法。

安装它:

dependencies:
  basic_utils: ^1.2.0

用途:

String reversed = StringUtils.reverse("helloworld");

Github:

https://github.com/Ephenodrom/Dart-Basic-Utils


1
投票

倒车

"Hello World"


0
投票

这是一个可用于反转字符串的函数。它接受一个字符串作为输入,并使用名为

Characters
的 dart 包从给定字符串中提取字符。然后我们可以将它们反转并再次连接以形成反转的字符串。

String reverse(String string) {
  if (string.length < 2) {
    return string;
  }

  final characters = Characters(string);
  return characters.toList().reversed.join();
}

0
投票

创建此扩展:

extension Ex on String {
  String get reverse => split('').reversed.join();
}

用途:

void main() {
  String string = 'Hello World';
  print(string.reverse); // dlroW olleH
}

0
投票

** 这是一个可用于反转字符串的函数。它接受一个字符串作为输入,并使用名为 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));
    }

0
投票

使用 StringBuffer:

String firstReverse(String str) {
      StringBuffer reversedStr = StringBuffer();
    
      for (int i = str.length - 1; i >= 0; i--) {
        reversedStr.write(str[i]);
      }
    
      return reversedStr.toString();
    }

带有代码单位:

String firstReverse(String str) {
  var stringToNumList = [];
  String reverseStr = '';

  for (var i = 0; i < str.length; i++) {
    stringToNumList.add(str[i].codeUnitAt(0));
  }

  int start = 0, last = stringToNumList.length - 1;

  while (start < last) {
    var temp = stringToNumList[start];
    stringToNumList[start] = stringToNumList[last];
    stringToNumList[last] = temp;
    start++;
    last--;
  }

  for (var i = 0; i < stringToNumList.length; i++) {
    reverseStr += String.fromCharCode(stringToNumList[i]);
  }

  return reverseStr;
}
© www.soinside.com 2019 - 2024. All rights reserved.