import 'dart:math' as math; import 'package:collection/collection.dart'; import 'package:np_math/np_math.dart'; extension ListExtension on List { Iterable takeIndex(List indexes) => indexes.map((e) => this[e]); List slice(int start, [int? stop, int step = 1]) { assert(step > 0); if (start < 0) { start = math.max(length + start, 0); } if (stop != null && stop < 0) { stop = math.max(length + stop, 0); } if (start >= length) { return []; } else if (stop == null) { final sub = sublist(start); if (step <= 1) { return sub; } else { return sub.whereIndexed((index, _) => index % step == 0).toList(); } } else if (start >= stop) { return []; } else { final sub = sublist(start, math.min(stop, length)); if (step <= 1) { return sub; } else { return sub.whereIndexed((index, _) => index % step == 0).toList(); } } } void stableSort([int Function(T a, T b)? compare]) { mergeSort(this, compare: compare); } /// In-place transform and return this /// /// Since the elements are in-place transformed, they have to share the same /// type List transform(T Function(T element) fn) { for (final i in 0.until(length)) { this[i] = fn(this[i]); } return this; } Future> asyncMap(Future Function(T element) fn) { return Stream.fromIterable(this).asyncMap(fn).toList(); } /// [map] with access to nearby elements /// /// Does not work well with nullable elements as prev and next return null for /// the first and last element Iterable map3(U Function(T e, T? prev, T? next) toElement) sync* { for (var i = 0; i < length; ++i) { yield toElement( this[i], i == 0 ? null : this[i - 1], i == length - 1 ? null : this[i + 1], ); } } /// [expand] with access to nearby elements /// /// Does not work well with nullable elements as prev and next return null for /// the first and last element Iterable expand3( Iterable Function(T e, T? prev, T? next) toElements) sync* { for (var i = 0; i < length; ++i) { yield* toElements( this[i], i == 0 ? null : this[i - 1], i == length - 1 ? null : this[i + 1], ); } } List added(T value) => toList()..add(value); List removed(T value) => toList()..remove(value); List removedAt(int index) => toList()..removeAt(index); List removedWhere(bool Function(T element) test) => toList()..removeWhere(test); }