LCOV - code coverage report
Current view: top level - collection-1.15.0/lib/src - list_extensions.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 129 0.0 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
       2             : // for details. All rights reserved. Use of this source code is governed by a
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : // Extension methods on common collection types.
       6             : import 'dart:collection';
       7             : import 'dart:math';
       8             : 
       9             : import 'algorithms.dart';
      10             : import 'algorithms.dart' as algorithms;
      11             : import 'equality.dart';
      12             : import 'utils.dart';
      13             : 
      14             : /// Various extensions on lists of arbitrary elements.
      15             : extension ListExtensions<E> on List<E> {
      16             :   /// Returns the index of [element] in this sorted list.
      17             :   ///
      18             :   /// Uses binary search to find the location of [element].
      19             :   /// The list *must* be sorted according to [compare],
      20             :   /// otherwise the result is unspecified
      21             :   ///
      22             :   /// Returns -1 if [element] does not occur in this list.
      23           0 :   int binarySearch(E element, int Function(E, E) compare) =>
      24           0 :       algorithms.binarySearchBy<E, E>(this, identity, compare, element);
      25             : 
      26             :   /// Returns the index of [element] in this sorted list.
      27             :   ///
      28             :   /// Uses binary search to find the location of [element].
      29             :   /// The list *must* be sorted according to [compare] on the [keyOf] of elements,
      30             :   /// otherwise the result is unspecified.
      31             :   ///
      32             :   /// Returns -1 if [element] does not occur in this list.
      33             :   ///
      34             :   /// If [start] and [end] are supplied, only the list range from [start] to [end]
      35             :   /// is searched, and only that range needs to be sorted.
      36           0 :   int binarySearchByCompare<K>(
      37             :           E element, K Function(E element) keyOf, int Function(K, K) compare,
      38             :           [int start = 0, int? end]) =>
      39           0 :       algorithms.binarySearchBy<E, K>(
      40             :           this, keyOf, compare, element, start, end);
      41             : 
      42             :   /// Returns the index of [element] in this sorted list.
      43             :   ///
      44             :   /// Uses binary search to find the location of [element].
      45             :   /// The list *must* be sorted according to the natural ordering of
      46             :   /// the [keyOf] of elements, otherwise the result is unspecified.
      47             :   ///
      48             :   /// Returns -1 if [element] does not occur in this list.
      49             :   ///
      50             :   /// If [start] and [end] are supplied, only the list range from [start] to [end]
      51             :   /// is searched, and only that range needs to be sorted.
      52           0 :   int binarySearchBy<K extends Comparable<K>>(
      53             :           E element, K Function(E element) keyOf, [int start = 0, int? end]) =>
      54           0 :       algorithms.binarySearchBy<E, K>(
      55           0 :           this, keyOf, (a, b) => a.compareTo(b), element, start, end);
      56             : 
      57             :   /// Returns the index where [element] should be in this sorted list.
      58             :   ///
      59             :   /// Uses binary search to find the location of [element].
      60             :   /// The list *must* be sorted according to [compare],
      61             :   /// otherwise the result is unspecified.
      62             :   ///
      63             :   /// If [element] is in the list, its index is returned,
      64             :   /// otherwise returns the first position where adding [element]
      65             :   /// would keep the list sorted. This may be the [length] of
      66             :   /// the list if all elements of the list compare less than
      67             :   /// [element].
      68           0 :   int lowerBound(E element, int Function(E, E) compare) =>
      69           0 :       algorithms.lowerBoundBy<E, E>(this, identity, compare, element);
      70             : 
      71             :   /// Returns the index where [element] should be in this sorted list.
      72             :   ///
      73             :   /// Uses binary search to find the location of [element].
      74             :   /// The list *must* be sorted according to [compare] of
      75             :   /// the [keyOf] of the elements, otherwise the result is unspecified.
      76             :   ///
      77             :   /// If [element] is in the list, its index is returned,
      78             :   /// otherwise returns the first position where adding [element]
      79             :   /// would keep the list sorted. This may be the [length] of
      80             :   /// the list if all elements of the list compare less than
      81             :   /// [element].
      82             :   ///
      83             :   /// If [start] and [end] are supplied, only that range is searched,
      84             :   /// and only that range need to be sorted.
      85           0 :   int lowerBoundByCompare<K>(
      86             :           E element, K Function(E) keyOf, int Function(K, K) compare,
      87             :           [int start = 0, int? end]) =>
      88           0 :       algorithms.lowerBoundBy(this, keyOf, compare, element, start, end);
      89             : 
      90             :   /// Returns the index where [element] should be in this sorted list.
      91             :   ///
      92             :   /// Uses binary search to find the location of [element].
      93             :   /// The list *must* be sorted according to the
      94             :   /// natural ordering of the [keyOf] of the elements,
      95             :   /// otherwise the result is unspecified.
      96             :   ///
      97             :   /// If [element] is in the list, its index is returned,
      98             :   /// otherwise returns the first position where adding [element]
      99             :   /// would keep the list sorted. This may be the [length] of
     100             :   /// the list if all elements of the list compare less than
     101             :   /// [element].
     102             :   ///
     103             :   /// If [start] and [end] are supplied, only that range is searched,
     104             :   /// and only that range need to be sorted.
     105           0 :   int lowerBoundBy<K extends Comparable<K>>(E element, K Function(E) keyOf,
     106             :           [int start = 0, int? end]) =>
     107           0 :       algorithms.lowerBoundBy<E, K>(
     108             :           this, keyOf, compareComparable, element, start, end);
     109             : 
     110             :   /// Takes an action for each element.
     111             :   ///
     112             :   /// Calls [action] for each element along with the index in the
     113             :   /// iteration order.
     114           0 :   void forEachIndexed(void Function(int index, E element) action) {
     115           0 :     for (var index = 0; index < length; index++) {
     116           0 :       action(index, this[index]);
     117             :     }
     118             :   }
     119             : 
     120             :   /// Takes an action for each element as long as desired.
     121             :   ///
     122             :   /// Calls [action] for each element.
     123             :   /// Stops iteration if [action] returns `false`.
     124           0 :   void forEachWhile(bool Function(E element) action) {
     125           0 :     for (var index = 0; index < length; index++) {
     126           0 :       if (!action(this[index])) break;
     127             :     }
     128             :   }
     129             : 
     130             :   /// Takes an action for each element and index as long as desired.
     131             :   ///
     132             :   /// Calls [action] for each element along with the index in the
     133             :   /// iteration order.
     134             :   /// Stops iteration if [action] returns `false`.
     135           0 :   void forEachIndexedWhile(bool Function(int index, E element) action) {
     136           0 :     for (var index = 0; index < length; index++) {
     137           0 :       if (!action(index, this[index])) break;
     138             :     }
     139             :   }
     140             : 
     141             :   /// Maps each element and its index to a new value.
     142             :   Iterable<R> mapIndexed<R>(R Function(int index, E element) convert) sync* {
     143             :     for (var index = 0; index < length; index++) {
     144             :       yield convert(index, this[index]);
     145             :     }
     146             :   }
     147             : 
     148             :   /// The elements whose value and index satisfies [test].
     149             :   Iterable<E> whereIndexed(bool Function(int index, E element) test) sync* {
     150             :     for (var index = 0; index < length; index++) {
     151             :       var element = this[index];
     152             :       if (test(index, element)) yield element;
     153             :     }
     154             :   }
     155             : 
     156             :   /// The elements whose value and index do not satisfy [test].
     157             :   Iterable<E> whereNotIndexed(bool Function(int index, E element) test) sync* {
     158             :     for (var index = 0; index < length; index++) {
     159             :       var element = this[index];
     160             :       if (!test(index, element)) yield element;
     161             :     }
     162             :   }
     163             : 
     164             :   /// Expands each element and index to a number of elements in a new iterable.
     165             :   ///
     166             :   /// Like [Iterable.expand] except that the callback function is supplied with
     167             :   /// both the index and the element.
     168             :   Iterable<R> expandIndexed<R>(
     169             :       Iterable<R> Function(int index, E element) expand) sync* {
     170             :     for (var index = 0; index < length; index++) {
     171             :       yield* expand(index, this[index]);
     172             :     }
     173             :   }
     174             : 
     175             :   /// Sort a range of elements by [compare].
     176           0 :   void sortRange(int start, int end, int Function(E a, E b) compare) {
     177           0 :     quickSortBy<E, E>(this, identity, compare, start, end);
     178             :   }
     179             : 
     180             :   /// Sorts elements by the [compare] of their [keyOf] property.
     181             :   ///
     182             :   /// Sorts elements from [start] to [end], defaulting to the entire list.
     183           0 :   void sortByCompare<K>(
     184             :       K Function(E element) keyOf, int Function(K a, K b) compare,
     185             :       [int start = 0, int? end]) {
     186           0 :     quickSortBy(this, keyOf, compare, start, end);
     187             :   }
     188             : 
     189             :   /// Sorts elements by the natural order of their [keyOf] property.
     190             :   ///
     191             :   /// Sorts elements from [start] to [end], defaulting to the entire list.
     192           0 :   void sortBy<K extends Comparable<K>>(K Function(E element) keyOf,
     193             :       [int start = 0, int? end]) {
     194           0 :     quickSortBy<E, K>(this, keyOf, compareComparable, start, end);
     195             :   }
     196             : 
     197             :   /// Shuffle a range of elements.
     198           0 :   void shuffleRange(int start, int end, [Random? random]) {
     199           0 :     RangeError.checkValidRange(start, end, length);
     200           0 :     shuffle(this, start, end, random);
     201             :   }
     202             : 
     203             :   /// Reverses the elements in a range of the list.
     204           0 :   void reverseRange(int start, int end) {
     205           0 :     RangeError.checkValidRange(start, end, length);
     206           0 :     while (start < --end) {
     207           0 :       var tmp = this[start];
     208           0 :       this[start] = this[end];
     209           0 :       this[end] = tmp;
     210           0 :       start += 1;
     211             :     }
     212             :   }
     213             : 
     214             :   /// Swaps two elements of this list.
     215           0 :   void swap(int index1, int index2) {
     216           0 :     RangeError.checkValidIndex(index1, this, 'index1');
     217           0 :     RangeError.checkValidIndex(index2, this, 'index2');
     218           0 :     var tmp = this[index1];
     219           0 :     this[index1] = this[index2];
     220           0 :     this[index2] = tmp;
     221             :   }
     222             : 
     223             :   /// A fixed length view of a range of this list.
     224             :   ///
     225             :   /// The view is backed by this this list, which must not
     226             :   /// change its length while the view is being used.
     227             :   ///
     228             :   /// The view can be used to perform specific whole-list
     229             :   /// actions on a part of the list.
     230             :   /// For example, to see if a list contains more than one
     231             :   /// "marker" element, you can do:
     232             :   /// ```dart
     233             :   /// someList.slice(someList.indexOf(marker) + 1).contains(marker)
     234             :   /// ```
     235           0 :   ListSlice<E> slice(int start, [int? end]) {
     236           0 :     end = RangeError.checkValidRange(start, end, length);
     237             :     var self = this;
     238           0 :     if (self is ListSlice) return self.slice(start, end);
     239           0 :     return ListSlice<E>(this, start, end);
     240             :   }
     241             : 
     242             :   /// Whether [other] has the same elements as this list.
     243             :   ///
     244             :   /// Returns true iff [other] has the same [length]
     245             :   /// as this list, and the elemets of this list and [other]
     246             :   /// at the same indices are equal according to [equality],
     247             :   /// which defaults to using `==`.
     248           0 :   bool equals(List<E> other, [Equality<E> equality = const DefaultEquality()]) {
     249           0 :     if (length != other.length) return false;
     250           0 :     for (var i = 0; i < length; i++) {
     251           0 :       if (!equality.equals(this[i], other[i])) return false;
     252             :     }
     253             :     return true;
     254             :   }
     255             : }
     256             : 
     257             : /// Various extensions on lists of comparable elements.
     258             : extension ListComparableExtensions<E extends Comparable<E>> on List<E> {
     259             :   /// Returns the index of [element] in this sorted list.
     260             :   ///
     261             :   /// Uses binary search to find the location of [element].
     262             :   /// The list *must* be sorted according to [compare],
     263             :   /// otherwise the result is unspecified.
     264             :   /// If [compare] is omitted, it uses the natural order of the elements.
     265             :   ///
     266             :   /// Returns -1 if [element] does not occur in this list.
     267           0 :   int binarySearch(E element, [int Function(E, E)? compare]) =>
     268           0 :       algorithms.binarySearchBy<E, E>(
     269             :           this, identity, compare ?? compareComparable, element);
     270             : 
     271             :   /// Returns the index where [element] should be in this sorted list.
     272             :   ///
     273             :   /// Uses binary search to find the location of where [element] should be.
     274             :   /// The list *must* be sorted according to [compare],
     275             :   /// otherwise the result is unspecified.
     276             :   /// If [compare] is omitted, it uses the natural order of the elements.
     277             :   ///
     278             :   /// If [element] does not occur in this list, the returned index is
     279             :   /// the first index where inserting [element] would keep the list
     280             :   /// sorted.
     281           0 :   int lowerBound(E element, [int Function(E, E)? compare]) =>
     282           0 :       algorithms.lowerBoundBy<E, E>(
     283             :           this, identity, compare ?? compareComparable, element);
     284             : 
     285             :   /// Sort a range of elements by [compare].
     286             :   ///
     287             :   /// If [compare] is omitted, the range is sorted according to the
     288             :   /// natural ordering of the elements.
     289           0 :   void sortRange(int start, int end, [int Function(E a, E b)? compare]) {
     290           0 :     RangeError.checkValidRange(start, end, length);
     291           0 :     algorithms.quickSortBy<E, E>(
     292             :         this, identity, compare ?? compareComparable, start, end);
     293             :   }
     294             : }
     295             : 
     296             : /// A list view of a range of another list.
     297             : ///
     298             : /// Wraps the range of the [source] list from [start] to [end]
     299             : /// and acts like a fixed-length list view of that range.
     300             : /// The source list must not change length while a list slice is being used.
     301             : class ListSlice<E> extends ListBase<E> {
     302             :   /// Original length of [source].
     303             :   ///
     304             :   /// Used to detect modifications to [source] which may invalidate
     305             :   /// the slice.
     306             :   final int _initialSize;
     307             : 
     308             :   /// The original list backing this slice.
     309             :   final List<E> source;
     310             : 
     311             :   /// The start index of the slice.
     312             :   final int start;
     313             : 
     314             :   @override
     315             :   final int length;
     316             : 
     317             :   /// Creates a slice of [source] from [start] to [end].
     318           0 :   ListSlice(this.source, this.start, int end)
     319           0 :       : length = end - start,
     320           0 :         _initialSize = source.length {
     321           0 :     RangeError.checkValidRange(start, end, source.length);
     322             :   }
     323             : 
     324             :   // No argument checking, for internal use.
     325           0 :   ListSlice._(this._initialSize, this.source, this.start, this.length);
     326             : 
     327             :   /// The end index of the slice.
     328           0 :   int get end => start + length;
     329             : 
     330           0 :   @override
     331             :   E operator [](int index) {
     332           0 :     if (source.length != _initialSize) {
     333           0 :       throw ConcurrentModificationError(source);
     334             :     }
     335           0 :     RangeError.checkValidIndex(index, this, null, length);
     336           0 :     return source[start + index];
     337             :   }
     338             : 
     339           0 :   @override
     340             :   void operator []=(int index, E value) {
     341           0 :     if (source.length != _initialSize) {
     342           0 :       throw ConcurrentModificationError(source);
     343             :     }
     344           0 :     RangeError.checkValidIndex(index, this, null, length);
     345           0 :     source[start + index] = value;
     346             :   }
     347             : 
     348           0 :   @override
     349             :   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     350           0 :     if (source.length != _initialSize) {
     351           0 :       throw ConcurrentModificationError(source);
     352             :     }
     353           0 :     RangeError.checkValidRange(start, end, length);
     354           0 :     source.setRange(start + start, start + end, iterable, skipCount);
     355             :   }
     356             : 
     357             :   /// A fixed length view of a range of this list.
     358             :   ///
     359             :   /// The view is backed by this this list, which must not
     360             :   /// change its length while the view is being used.
     361             :   ///
     362             :   /// The view can be used to perform specific whole-list
     363             :   /// actions on a part of the list.
     364             :   /// For example, to see if a list contains more than one
     365             :   /// "marker" element, you can do:
     366             :   /// ```dart
     367             :   /// someList.slice(someList.indexOf(marker) + 1).contains(marker)
     368             :   /// ```
     369           0 :   ListSlice<E> slice(int start, [int? end]) {
     370           0 :     end = RangeError.checkValidRange(start, end, length);
     371           0 :     return ListSlice._(_initialSize, source, start + start, end - start);
     372             :   }
     373             : 
     374           0 :   @override
     375             :   void shuffle([Random? random]) {
     376           0 :     if (source.length != _initialSize) {
     377           0 :       throw ConcurrentModificationError(source);
     378             :     }
     379           0 :     algorithms.shuffle(source, start, end, random);
     380             :   }
     381             : 
     382           0 :   @override
     383             :   void sort([int Function(E a, E b)? compare]) {
     384           0 :     if (source.length != _initialSize) {
     385           0 :       throw ConcurrentModificationError(source);
     386             :     }
     387             :     compare ??= defaultCompare;
     388           0 :     quickSort(source, compare, start, start + length);
     389             :   }
     390             : 
     391             :   /// Sort a range of elements by [compare].
     392           0 :   void sortRange(int start, int end, int Function(E a, E b) compare) {
     393           0 :     if (source.length != _initialSize) {
     394           0 :       throw ConcurrentModificationError(source);
     395             :     }
     396           0 :     source.sortRange(start, end, compare);
     397             :   }
     398             : 
     399             :   /// Shuffles a range of elements.
     400             :   ///
     401             :   /// If [random] is omitted, a new instance of [Random] is used.
     402           0 :   void shuffleRange(int start, int end, [Random? random]) {
     403           0 :     if (source.length != _initialSize) {
     404           0 :       throw ConcurrentModificationError(source);
     405             :     }
     406           0 :     RangeError.checkValidRange(start, end, length);
     407           0 :     algorithms.shuffle(source, this.start + start, this.start + end, random);
     408             :   }
     409             : 
     410             :   /// Reverses a range of elements.
     411           0 :   void reverseRange(int start, int end) {
     412           0 :     RangeError.checkValidRange(start, end, length);
     413           0 :     source.reverseRange(this.start + start, this.start + end);
     414             :   }
     415             : 
     416             :   // Act like a fixed-length list.
     417             : 
     418           0 :   @override
     419             :   set length(int newLength) {
     420           0 :     throw UnsupportedError('Cannot change the length of a fixed-length list');
     421             :   }
     422             : 
     423           0 :   @override
     424             :   void add(E element) {
     425           0 :     throw UnsupportedError('Cannot add to a fixed-length list');
     426             :   }
     427             : 
     428           0 :   @override
     429             :   void insert(int index, E element) {
     430           0 :     throw UnsupportedError('Cannot add to a fixed-length list');
     431             :   }
     432             : 
     433           0 :   @override
     434             :   void insertAll(int index, Iterable<E> iterable) {
     435           0 :     throw UnsupportedError('Cannot add to a fixed-length list');
     436             :   }
     437             : 
     438           0 :   @override
     439             :   void addAll(Iterable<E> iterable) {
     440           0 :     throw UnsupportedError('Cannot add to a fixed-length list');
     441             :   }
     442             : 
     443           0 :   @override
     444             :   bool remove(Object? element) {
     445           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     446             :   }
     447             : 
     448           0 :   @override
     449             :   void removeWhere(bool Function(E element) test) {
     450           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     451             :   }
     452             : 
     453           0 :   @override
     454             :   void retainWhere(bool Function(E element) test) {
     455           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     456             :   }
     457             : 
     458           0 :   @override
     459             :   void clear() {
     460           0 :     throw UnsupportedError('Cannot clear a fixed-length list');
     461             :   }
     462             : 
     463           0 :   @override
     464             :   E removeAt(int index) {
     465           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     466             :   }
     467             : 
     468           0 :   @override
     469             :   E removeLast() {
     470           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     471             :   }
     472             : 
     473           0 :   @override
     474             :   void removeRange(int start, int end) {
     475           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     476             :   }
     477             : 
     478           0 :   @override
     479             :   void replaceRange(int start, int end, Iterable<E> newContents) {
     480           0 :     throw UnsupportedError('Cannot remove from a fixed-length list');
     481             :   }
     482             : }

Generated by: LCOV version 1.14