https://github.com/simphotonics/stride
Extension method for iterating Dart Lists and Iterables using a custom start index and step size (stride).
https://github.com/simphotonics/stride
array column-major dart iterable iterator multi-dimensional-array numerical-computation row-major stride
Last synced: about 2 months ago
JSON representation
Extension method for iterating Dart Lists and Iterables using a custom start index and step size (stride).
- Host: GitHub
- URL: https://github.com/simphotonics/stride
- Owner: simphotonics
- License: bsd-3-clause
- Created: 2021-06-06T08:29:43.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2024-04-15T21:32:09.000Z (over 1 year ago)
- Last Synced: 2025-02-14T00:17:21.786Z (10 months ago)
- Topics: array, column-major, dart, iterable, iterator, multi-dimensional-array, numerical-computation, row-major, stride
- Language: Dart
- Homepage: https://pub.dev/packages/stride
- Size: 209 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Dart Stride Iterators
[](https://github.com/simphotonics/stride/actions/workflows/dart.yml)
## Introduction
The package [stride][stride] provides **stride iterators** and extension
methods that make it possible to iterate data structures of type `List` and
`Iterable` using a custom start point and step size. For negative step sizes
a reverse iterator is used.
## Multi-Dimensional Arrays
In Dart, a multi-dimensional array can be
represented as a list of lists.
However, in the context of
[numerical computation](https://dart.dev/articles/archive/numeric-computation)
it is often useful to store multi-dimensional arrays as a flat list
to speed up arithmetical operations and minimize memory usage.
The example below shows how the elements of a 2-dimensional array can
be stored as a 1-dimensional array (a Dart list).

In order to access the elements of the column with index 1
(highlighted using a grey rectangle), we
need to start the iteration at index 1. To move to the next element
we have to use a step size, or **stride**, that is equal to the
number of columns in the 2D-array. For more
info, see the section on [storage layout](#storage-layout) below.
## Usage
To use this package, include [stride] as a dependency in your `pubspec.yaml` file.
The program below demonstrates how to use the
extension method [`stride`][stride-method] to iterate lists using a custom step size
and start index. Note that the iteration step size must not be zero. A negative step
size and suitable start index may be used to iterate in reverse direction.
Tip: When iterating *fixed* size lists, immutable lists views, or typed lists
it makes perfect sense to omit concurrent modification
checks by using the method [`fastStride`][fastStride-method].
The slight performance improvement
is evident when iterating very long lists.
```Dart
import 'dart:typed_data';
import 'package:stride/stride.dart';
main(List args) {
// 3x3 matrix.
final array2D = >[
['e00', 'e01', 'e02'],
['e10', 'e11', 'e12'],
['e20', 'e21', 'e22'],
];
/// Elements of 3x3 matrix in row major layout.
final list = ['e00', 'e01', 'e02', 'e10', 'e11', 'e12', 'e20', 'e21', 'e22'];
final stepSize = 3;
final startIndex = 1;
final strideIt0 = list.stride(stepSize, startIndex);
print('2D array:');
print(array2D[0]);
print(array2D[1]);
print(array2D[2]);
print('');
print('Column 1:');
print(strideIt0);
print('');
// Typed list (with fixed length).
final numericalList =
Float64List.fromList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
// Omitting concurrent modification checks:
final strideIt1 = numericalList.fastStride(
stepSize,
startIndex
);
print('Numerical list:');
print(numericalList);
print('');
print('start index: 1 and step-size: 3:');
print(strideIt1);
print('');
print('start index: 9 and step-size: -3:');
final reverseStrideIt1 = numericalList.stride(-3, 9);
print(reverseStrideIt1);
}
```
Running the program above produces the following console output:
```Console
$ dart example/bin/example.dart
2D array:
[e00, e01, e02]
[e10, e11, e12]
[e20, e21, e22]
Column 1:
(e01, e11, e21)
Numerical list:
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
start index: 1 and step-size: 3:
(1.0, 4.0, 7.0, 10.0)
start index: 9 and step-size: -3:
(9.0, 6.0, 3.0, 0.0)
```
## Storage Layout
Let **A** be an n-dimensional array with length di along dimension i,
where i ∈ \[0, n-1\].
Let **L** be a Dart list containing all the elements of **A**. Then the length of **L** will be d0 × d1 × … × dn-1 .
Let the element **A**\[ i0 \]\[ i1 \]…\[ in‑1 \] be stored at location **L**\[s0×i0 + … + sn-1×in-1\].
Then the iteration step sizes, si depend on the storage order
as shown below.
### Row Major Layout
For a *row major* storage order the step sizes are given by:
s0 = d1 · d2 · … · dn-1
s1 = d2 · d3 · … · dn-1
⋮
sn-2 = dn-1
sn-1 = 1.
### Column Major Layout
For a *column major* storage order the step sizes are given by:
s0 = 1
s1 = d0
s2 = d0 · d1
⋮
sn-2 = d0 · d1 · … · dn-3
sn-1 = d0 · d1 · … · dn-2
For more information see [Row- and column-major order](https://en.wikipedia.org/wiki/Row-_and_column-major_order).
## Examples
A copy of the program shown in the section above can be found in the folder [example].
## Features and bugs
Please file feature requests and bugs at the [issue tracker].
[issue tracker]: https://github.com/simphotonics/stride/issues
[example]: https://github.com/simphotonics/stride/tree/main/example
[stride]: https://pub.dev/packages/stride
[Stride]: https://pub.dev/documentation/stride/latest/stride/Stride.html
[stride-method]: https://pub.dev/documentation/stride/latest/stride/Stride/stride.html
[fastStride-method]: https://pub.dev/documentation/stride/latest/stride/FastStride/fastStride.html