【问题标题】:Dart: create a list from 0 to NDart:创建一个从 0 到 N 的列表
【发布时间】:2016-10-14 09:10:33
【问题描述】:

如何在 dart 中轻松创建一系列连续整数?例如:

// throws a syntax error :)
var list = [1..10];

【问题讨论】:

    标签: list dart range


    【解决方案1】:

    据我所知,在 Dart 中没有等效的原生方法。但是,您可以创建自己的 Range 类,或者如果您不介意依赖关系,可以使用 https://pub.dartlang.org/packages/range

    Olov Lassus 不久前写了 an article 关于实现自己的 Range 类

    编辑:我刚刚想到的更好的方法:

    Iterable<int> range(int low, int high) sync* {
      for (int i = low; i < high; ++i) {
        yield i;
      }
    }
    
    void main() {
      for(final i in range(1, 20)) {
        print(i);
      }
    }
    

    【讨论】:

    • 我真的认为@Alexandre Ardhuin 的回答更好:P
    • 这个包与 Dart2 不兼容
    【解决方案2】:

    您可以使用List.generate constructor

    var list = new List<int>.generate(10, (i) => i + 1);
    

    您也可以使用生成器:

    /// the list of positive integers starting from 0
    Iterable<int> get positiveIntegers sync* {
      int i = 0;
      while (true) yield i++;
    }
    void main() {
      var list = positiveIntegers
          .skip(1)   // don't use 0
          .take(10)  // take 10 numbers
          .toList(); // create a list
      print(list);   // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    }
    

    在 Dart 2.3 之后你可以使用collection for:

    var list = [for (var i = 1; i <= 10; i++) i];
    

    【讨论】:

    • 那很好,不过我觉得 Dart 应该支持 [1..N] 语法,因为这是很常见的东西。
    • 我一直想要a.to(b) 有一段时间了。至少对于List.generate,如果您想从 0 开始,我认为第二个参数是可选的。
    • 这是使用循环静态初始化final的好方法。
    • 解决方案可以通过删除 new 关键字来缩短一点,在这种情况下不需要这样做。
    【解决方案3】:

    你也可以使用 Dart 的 Iterable.generate 函数来创建一个介于 0..n-1 之间的范围

    var list = Iterable<int>.generate(10).toList()
    // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    【讨论】:

      【解决方案4】:

      dart 2.3.0

      var list = [for(var i=0; i<10; i+=1) i];
      

      【讨论】:

      • 这被称为“收集”。它与“for 语句”不同。
      • 如此可爱、简单且可定制!
      【解决方案5】:

      我一直在使用 Alexandre Ardhuin 的修改版本,它试图模仿 python 提供的 range() 编辑:发现可选的位置参数是下面的更新代码

      range(int stop, {int start: 0, int step: 1}){
        if (step == 0)
          throw Exception("Step cannot be 0");
      
        return start < stop == step > 0
        ? List<int>.generate(((start-stop)/step).abs().ceil(), (int i) => start + (i * step))
        : [];
      }
      

      示例用法:

      range(16, start:-5, step: 8);
      // [-5, 3, 11]
      range(5);
      // [0, 1, 2, 3, 4]
      

      不幸的是,我没有完全模仿 python (range(start, stop[, step])) 的简单语法,因为 dart 没有运算符重载或可选的位置参数。

      使用类似于 Maryan 的解决方案的列表理解的另一个选项

      listCompRange(int start, int stop, int step) {
        if (step == 0)
          throw Exception("Step cannot be 0");
        if (start == stop)
          return [];
        bool forwards = start < stop;
        return forwards == step > 0
        ? forwards 
          ? [for (int i = 0; i*step < stop-start; i++) start + (i * step)]
          : [for (int i = 0; i*step > stop-start; i++) start + (i * step)]
        : [];
      }
      

      示例用法:

      listCompRange(0, 5, 1);
      // [0, 1, 2, 3, 4]
      

      我使用以下方法对这两个选项进行了基准测试

      benchMarkRange(){
        List<List<int>> temp = List<List<int>>();
        Stopwatch timer = Stopwatch();
        timer.start();
        for (int i = 0; i < 500; i++){
          temp.add(range(-30, start: -10, step: -2));
        }
        timer.stop();
        print("Range function\n${timer.elapsed}\n");
        return temp;
      }
      
      benchMarkListComprehension(){
        List<List<int>> temp = List<List<int>>();
        Stopwatch timer = Stopwatch();
        timer.start();
        for (int i = 0; i < 500; i++){
          temp.add(listCompRange(-10, -30, -2));
        }
        timer.stop();
        print("List comprehension\n${timer.elapsed}\n");
        return temp;
      }
      

      产生的这些结果稍微有利于生成器。

      Range function
      0:00:00.011953
      0:00:00.011558
      0:00:00.011473
      0:00:00.011615
      
      List comprehension
      0:00:00.016281
      0:00:00.017403
      0:00:00.017496
      0:00:00.016878
      

      但是,当我将函数从 -10 更改为 -30,步长为 -2 时,结果略微偏向于列表理解。

      List comprehension
      0:00:00.001352             
      0:00:00.001328                
      0:00:00.001300
      0:00:00.001335
      
      Range function
      0:00:00.001371
      0:00:00.001466
      0:00:00.001438
      0:00:00.001372
      

      使用位置参数而不是命名参数更新代码

      range(int a, [int stop, int step]) {
        int start;
      
        if (stop == null) {
          start = 0;
          stop = a;
        } else {
          start = a;
        }  
      
        if (step == 0)
          throw Exception("Step cannot be 0");
      
        if (step == null)
          start < stop 
          ? step = 1    // walk forwards
          : step = -1;  // walk backwards
      
        // return [] if step is in wrong direction
        return start < stop == step > 0
        ? List<int>.generate(((start-stop)/step).abs().ceil(), (int i) => start + (i * step))
        : [];
      }
      

      用法:range(int a, [int stop, int step])

      如果 stop 不包括在内,则 a 变为 stop 并且 start 将默认为 0 如果同时提供 a 和 stop,则 a 变为 start 如果未提供,则 step 将默认为 1 或 -1,具体取决于 start 或 stop 是否更大

      range(4);
      // [0, 1, 2, 3]
      range(4, 10);
      // [4, 5, 6, 7, 8, 9]
      range(4, 10, 2);
      // [4, 6, 8]
      range(-4);
      // [0, -1, -2, -3]
      range(10, 4);
      // [10, 9, 8, 7, 6, 5]
      range(10,10);
      // []
      range(1, 2, -1);
      // []
      range(x, y, 0);
      // Exception
      

      【讨论】:

        【解决方案6】:

        Quiver 包中定义了许多类似 Python 的迭代器。

        例如,使用range()函数:

        import 'package:quiver/iterables.dart';
        
        print(range(10).toList().toString());
        

        输出:

        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        

        它在forloops 中也可以正常工作:

        for (var i in range(1, 11))
          print('$i');
        

        还提供了很多其他useful iterators

        【讨论】:

          【解决方案7】:

          @Ganymede:

          这是一个简单的 a.to(b) 解决方案:

          extension RangeExtension on int {
            List<int> to(int maxInclusive) =>
              [for (int i = this; i <= maxInclusive; i++) i];
          }
          

          或可选步骤:

          
          extension RangeExtension on int {
            List<int> to(int maxInclusive, {int step = 1}) =>
                [for (int i = this; i <= maxInclusive; i += step) i];
          }
          

          像这样使用最后一个:

          void main() {
            // [5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50]
            print(5.to(50, step: 3));
          }
          

          【讨论】:

            【解决方案8】:

            我的方法可能不是创建 N..M 列表的最优雅的解决方案,但它非常有用且易于实现:

            void main() {
              generateN2MList(2, 8);
              generateN2MList(4, 10);
              generateN2MList(1, 3);
              generateN2MList(0, 13, true);
            }
            
            void generateN2MList(int n, int m, [bool excludeLimits = false]) {
              final diff = m - n;
              final times = excludeLimits ? diff - 1 : diff + 1;
              final startingIdx = excludeLimits ? n + 1 : n;
              List<int> generated =
                  List.generate(times, (i) => startingIdx + i);
            
              print(generated);
            }
            
            

            如果我们尝试一下,结果如下:

            [2, 3, 4, 5, 6, 7, 8]
            [4, 5, 6, 7, 8, 9, 10]
            [1, 2, 3]
            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
            

            Here's a DartPad if you want to play around with it.

            【讨论】:

            • i == 0 ? startingIdx : startingIdx + i 我认为这有点多余,因为如果 i 为 0 那么 startingIdx = startingIdx + i 反正
            • 你是对的!我刚刚更新了我的答案,感谢您指出这一点!
            【解决方案9】:
            void main() {
              print(List.generate(10, (index) => index));
            }
            
            
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
            

            List.generate 返回新列表

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-05-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多