Dart:创建一个从0到N的列表

Ceq*_*iel 29 list range dart

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

// throws a syntax error :)
var list = [1..10];
Run Code Online (Sandbox Code Playgroud)

Ale*_*uin 49

您可以使用List.generate构造函数:

var list = new List<int>.generate(10, (i) => i + 1);
Run Code Online (Sandbox Code Playgroud)

您可以替代使用生成器:

/// 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]
}
Run Code Online (Sandbox Code Playgroud)

  • 很好,但是我认为Dart应该支持[1..N]语法,因为这是很常见的事情。 (3认同)
  • 我一直想要`a.to(b)` 一段时间了。至少对于 `List.generate` 我认为如果你想从 0 开始,第二个参数是可选的。 (2认同)

Dav*_*ees 13

您还可以使用Dart的Iterable.generate函数创建介于0..n-1之间的范围

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

  • 我更倾向于使用它而不是“List.generate”,因为它不需要显式生成器。 (2认同)

Mar*_*yan 13

使用dart 2.3.0

var list = [for(var i=0; i<10; i+=1) i];
Run Code Online (Sandbox Code Playgroud)


Sac*_*lal 11

void main() {
  print(List.generate(10, (index) => index));
}


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

List.generate返回新列表


小智 10

@Ganymede:

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

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

或使用可选步骤:


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

像这样使用最后一个:

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


Pac*_*ane 6

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

Olov Lassus写了一篇关于在不久前实现自己的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);
  }
}
Run Code Online (Sandbox Code Playgroud)


ale*_*rst 6

我一直在使用 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))
  : [];
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

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

不幸的是,我并没有完全模仿 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)]
  : [];
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

listCompRange(0, 5, 1);
// [0, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

这产生了对生成器稍微有利的结果。

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
Run Code Online (Sandbox Code Playgroud)

然而,当我将函数从 -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
Run Code Online (Sandbox Code Playgroud)

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

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))
  : [];
}
Run Code Online (Sandbox Code Playgroud)

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

如果不包含 stop,则 a 变为 stop,start 将默认为 0 如果同时提供 a 和 stop,则如果未提供,则变为 start,步长将默认为 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
Run Code Online (Sandbox Code Playgroud)


Ber*_*Ber 6

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

例如,使用range()函数:

import 'package:quiver/iterables.dart';

print(range(10).toList().toString());
Run Code Online (Sandbox Code Playgroud)

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

它在for循环中也能正常工作:

for (var i in range(1, 11))
  print('$i');
Run Code Online (Sandbox Code Playgroud)

还提供了许多其他有用的迭代器