【问题标题】:How do I reverse a String in Dart?如何在 Dart 中反转字符串?
【发布时间】:2014-02-26 14:33:46
【问题描述】:

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

例子:

Hello, world

应该变成:

dlrow ,olleH

我还应该考虑带有 Unicode 字符的字符串。例如:'Ame\u{301}lie'

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

【问题讨论】:

  • 您能否提供一个有用的示例。现在有很多答案对许多输入都没有做正确的事情,因为您没有指定具有严格限制的用例,以便反转字符串起作用。到目前为止,没有一个答案适用于像'Ame\u{301}lie' 这样的简单输入。
  • @FlorianLoitsch 我正在编写一个 Angular 过滤器作为演示。制作一个反转字符串的过滤器很简单。我将在问题中澄清我的用例是什么。

标签: string flutter dart split reverse


【解决方案1】:

这是一个可以用来反转字符串的函数。它将一个字符串作为输入,并将使用一个名为 Characters 的 dart 包从给定的字符串中提取字符。然后我们可以将它们反转并再次连接以形成反转的字符串。

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

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

【讨论】:

    【解决方案2】:

    在 Dart 中有很多方法可以反转字符串,下面给出了其中的一些。

    使用拆分和连接:

    String reverseStringUsingSplit(String input) {
      var chars = input.split('');
      return chars.reversed.join();
    }
    

    使用符文:

    String reverseStringUsingRunes(String input) {
      var chars = input.runes.toList();
    
      return String.fromCharCodes(chars.reversed);
    }
    

    使用 codeUnits:

    String reverseStringUsingCodeUnits(String input) {
      return String.fromCharCodes(input.codeUnits.reversed);
    }
    

    你可以像这样简单地使用所有方法

    void main() {
      var coflutter = 'Coflutter';
    
      print(reverseStringUsingSplit(coflutter));
      print(reverseStringUsingRunes(coflutter));
      print(reverseStringUsingCodeUnits(coflutter));
    }
    

    所有 3 个方法的输出将是

    rettulfoC
    rettulfoC
    rettulfoC
    

    参考:https://coflutter.com/dart-how-to-reverse-a-string/

    【讨论】:

      【解决方案3】:

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

      安装它:

      dependencies:
        basic_utils: ^1.2.0
      

      用法:

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

      Github:

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

      【讨论】:

        【解决方案4】:

        这个问题没有很好的定义。反转任意字符串没有意义,并且会导致输出中断。第一个(可克服的)障碍是 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),则在技术上可以反转字符串。但是,我还没有看到一个用例表明这个操作是有意义的。

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

        以英语为母语的人尤其要注意:字符串很少能像单个字符的列表一样处理。在几乎所有其他语言中,这都会导致程序错误。 (不要让我开始使用 toLowerCasetoUpperCase ...)。

        【讨论】:

        • 我从这个简单的问答中学到了很多,现在我想知道toLowerCasetoUpperCase 是怎么回事。
        • @André 我认为他的意思是假设所有语言都有其字符的大写/小写表示......就像在表情符号 UTF32 代码中调用 toLowerCase,如 \u{1d11e} ?
        • @mFeinstein 它也可能指Turkish İ problem 之类的情况,根据语言环境可能导致比较失败
        • 也是希腊语:像 άσος 这样的词应该是全大写的 ΑΣΟΣ(没有变音符号),但 Άσος(有变音符号)在句首。
        【解决方案5】:

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

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

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

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

        【讨论】:

        • 这不是快速的方法,因为它会创建 List。如果你有大长度的字符串,它会创建很多字符串。输入字符串中每个代码单元一个字符串。这不是有效的方法。
        • Mezoni 是对的:他的解决方案更简单、更快。
        • 谢谢。我会澄清一下,我的回答并不是最快的方法。
        • @FlorianLoitsch 我用上面的方法测试了“Ame\u{301}lie”,结果却相反。有哪些失败的字符串? print('Ame\u{301}lie'.split('').reversed.join('')); ==> eiĺemA
        • 这不是正确的逆。重音在“l”而不是“e”。另外:这只是符文需要按顺序排列的示例。如果你有代理对,那就更糟了:“为胜利而音乐 \u{1d11e}”。
        【解决方案6】:

        我为几个不同的选择做了一个小基准:

        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)
        

        【讨论】:

        • 不是一个主要的添加,但是在上一个例子中减少循环而不是增加循环理论上应该使它更快
        • 最后一个有问题。但基准提供了有用的信息。
        • 甜蜜! time() 方法?是来自某种包裹吗?
        【解决方案7】:

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

        import 'package:more/iterable.dart';
        
        void main() {
          print(string('Hello World').reversed.join());
        }
        

        【讨论】:

          【解决方案8】:

          试试这个功能

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

          【讨论】:

          • 由于排名较高的答案中描述的原因,这已被破坏。
          猜你喜欢
          • 1970-01-01
          • 2022-12-19
          • 2018-12-08
          • 1970-01-01
          • 2016-08-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多