Dart: create a list from 0 to N

ListDartRange

List Problem Overview


How can I create easily a range of consecutive integers in dart? For example:

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

List Solutions


Solution 1 - List

You can use the List.generate constructor :

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

You can alternativelly use a generator:

/// 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]
}

After Dart 2.3 you can use collection for:

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

Solution 2 - List

with dart 2.3.0 :

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

Solution 3 - List

You can also use Dart's Iterable.generate function to create a range between 0..n-1

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

Solution 4 - List

@Ganymede:

here's a simple a.to(b) solution:

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

or with optional step:


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

use the last one like this:

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

Solution 5 - List

As far as I know there's no native equivalent way of doing this in Dart. However you can create your own Range class, or use https://pub.dartlang.org/packages/range if you don't mind the dependency.

Olov Lassus wrote an article about implementing your own Range class a while back

edit: an even better way I just thought of:

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

Solution 6 - List

There are many Python-like iterators defined in the Quiver package.

For example, use the range() function:

import 'package:quiver/iterables.dart';

print(range(10).toList().toString());

Output:

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

It also works fine in forloops:

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

Lots of other useful iterators are also provided.

Solution 7 - List

I have been using a modified version of Alexandre Ardhuin's which tries to mimic the range() provided by python Edit: found out optional positional arguments are a thing updated code below

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))
  : [];
}

Example Usage:

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

Unfortunately I have not entirely mimicked the easier syntax of python (range(start, stop[, step])) as dart doesn't have operator overloading or optional positional arguments.

Another option using list comprehension which resembles Maryan's solution

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)]
  : [];
}

Example Usage:

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

I benchmarked both of these options with the following methods

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

which yielded these results slightly favoring the generator.

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

however when I changed the function to generate from -10 to -30 with a step of -2 the results slightly favored the list comprehension.

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

Updated code with positional rather than named parameters

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))
  : [];
}

Usage: range(int a, [int stop, int step])

If stop is not included a becomes stop and start will default to 0 If a and stop are both provided a becomes start if not provided step will default to 1 or -1 depending on whether start or stop is larger

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

Solution 8 - List

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


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

List.generate returns new list

Solution 9 - List

Mine might not be the most elegant solution to create a N..M list, but it was useful and simple enough to implement:

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

And if we try it out, here's the result:

[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.

Solution 10 - List

If you want to create truly range and then be able to compere different ranges with each other you can consider the range_type.

  final july = DateTimeRange.parse('[2022-07-01, 2022-08-01)');
  final scheduleDate1 = DateTime(2022, 07, 02);
  final scheduleDate2 = DateTime(2022, 08, 07);
  final workingDays = DateTimeRange.parse('[2022-07-20, 2022-08-15)');
  print('Is scheduleDate1 in July? ${july.containsElement(scheduleDate1)}');
  print('Is scheduleDate2 in July? ${july.containsElement(scheduleDate2)}');
  print('Is workingDays overlaps? ${july.overlap(workingDays)}');
  print('workingDays intersection: ${july.intersection(workingDays)}');
  print('workingDays union: ${july.union(workingDays)}');
  print('july difference workingDays: ${july.difference(workingDays)}');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCequielView Question on Stackoverflow
Solution 1 - ListAlexandre ArdhuinView Answer on Stackoverflow
Solution 2 - ListMaryanView Answer on Stackoverflow
Solution 3 - ListDavid ReesView Answer on Stackoverflow
Solution 4 - ListMichaelView Answer on Stackoverflow
Solution 5 - ListPacaneView Answer on Stackoverflow
Solution 6 - ListBerView Answer on Stackoverflow
Solution 7 - ListalexanderhurstView Answer on Stackoverflow
Solution 8 - ListSachin ChillalView Answer on Stackoverflow
Solution 9 - ListAlejandroView Answer on Stackoverflow
Solution 10 - ListCyraxView Answer on Stackoverflow