Line data Source code
1 : import 'dart:collection'; 2 : import 'dart:math' as math; 3 : 4 : /// {@template collection.iterable_extensions} 5 : /// [Iterable] extension methods. 6 : /// {@endtemplate} 7 : extension BatteriesIterableX<T> on Iterable<T> { 8 : /// Chunk while 9 1 : Iterable<List<T>> chunkWhile(bool Function(T a, T b) test) sync* { 10 1 : final i = iterator; 11 3 : var list = i.moveNext() ? <T>[i.current] : <T>[]; 12 1 : while (i.moveNext()) { 13 3 : if (test(list.last, i.current)) { 14 2 : list.add(i.current); 15 : } else { 16 : yield list; 17 2 : list = <T>[i.current]; 18 : } 19 : } 20 1 : if (list.isNotEmpty) yield list; 21 : } 22 : 23 : /// Split when 24 1 : Iterable<List<T>> splitWhen(bool Function(T a, T b) test) => 25 3 : chunkWhile((a, b) => !test(a, b)); 26 : 27 : /// Allow relieve impact on event loop on large collections. 28 : /// Parallelize the event queue and free up time for processing animation, 29 : /// user gestures without using isolates. 30 : /// 31 : /// [duration] - elapsed time of iterations before releasing 32 : /// the event queue and microtasks. 33 1 : Stream<T> relieve([ 34 : Duration duration = const Duration(milliseconds: 4), 35 : ]) async* { 36 2 : final sw = Stopwatch()..start(); 37 : try { 38 1 : final iter = iterator; 39 1 : while (iter.moveNext()) { 40 2 : if (sw.elapsed > duration) { 41 2 : await Future<void>.delayed(Duration.zero); 42 1 : sw.reset(); 43 : } 44 2 : yield iter.current; 45 : } 46 : } finally { 47 1 : sw.stop(); 48 : } 49 : } 50 : 51 : /// Return only unique elements from the iterable. 52 : /// [hash] function ussumally returning id of the element. 53 1 : Iterable<T> distinct([Object? Function(T a)? hash]) { 54 : if (hash != null) { 55 1 : final set = HashSet<Object?>(); 56 4 : return where((e) => set.add(hash(e))); 57 : } else { 58 1 : final set = HashSet<T>(); 59 2 : return where(set.add); 60 : } 61 : } 62 : } 63 : 64 : /// {@template iterable.code_units} 65 : /// Iterable<int> as code units. 66 : /// {@endtemplate} 67 : extension BatteriesCodeUnitsX on Iterable<int> { 68 : /// Check code is digit 69 : /// 0..9: 48..57 70 3 : static bool isDigit(int code) => code > 47 && code < 58; 71 : 72 : /// Check code is lattin letter 73 : /// A..Z: 65..90 74 : /// a..z: 97..122 75 1 : static bool isLatin(int code) => 76 4 : (code > 64 && code < 91) || (code > 96 && code < 123); 77 : 78 : /// Check code is cyrillic letter 79 : /// Ё: 1025 80 : /// А..Я: 1040..1071 81 : /// а..я: 1072..1103 82 : /// ё: 1105 83 1 : static bool isCyrillic(int code) => 84 4 : (code > 1039 && code < 1104) || code == 1025 || code == 1105; 85 : 86 : /// Get from iterable only digits symbols 87 2 : Iterable<int> get onlyDigits => where(isDigit); 88 : 89 : /// Get from iterable only latin symbols 90 2 : Iterable<int> get onlyLatin => where(isLatin); 91 : 92 : /// Get from iterable only cyrillic symbols 93 2 : Iterable<int> get onlyCyrillic => where(isCyrillic); 94 : 95 : /// Maximum code 96 2 : int get max => reduce(math.max); 97 : 98 : /// Minimum code 99 2 : int get min => reduce(math.min); 100 : }