From cbbe5ad4e511b10d707b90850d3d61de14c9df04 Mon Sep 17 00:00:00 2001 From: gmpassos Date: Sat, 21 Dec 2024 04:59:19 -0300 Subject: [PATCH] v3.2.3 - sdk: '>=3.4.0 <4.0.0' - lints: ^4.0.0 - test: ^1.25.14 - dependency_validator: ^4.1.2 - coverage: ^1.11.1 --- CHANGELOG.md | 12 +++ lib/src/collections.dart | 192 ++++++++++++++++++++++--------------- lib/src/date.dart | 4 - pubspec.yaml | 12 +-- test/swiss_knife_test.dart | 16 ++++ 5 files changed, 149 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc81811..b0407a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 3.2.3 + +- Optimize `toFlatListOfStrings`. +- Added `trimListOfStrings`. + +- sdk: '>=3.4.0 <4.0.0' + +- lints: ^4.0.0 +- test: ^1.25.14 +- dependency_validator: ^4.1.2 +- coverage: ^1.11.1 + ## 3.2.2 - `MimeType`: diff --git a/lib/src/collections.dart b/lib/src/collections.dart index f8be8a9..f8ac945 100644 --- a/lib/src/collections.dart +++ b/lib/src/collections.dart @@ -732,54 +732,83 @@ final RegExp _toListOfStringsDelimiter = RegExp(r'\s+'); /// Converts any collection to a flat list of strings. List toFlatListOfStrings(Object? s, {Pattern? delimiter, bool trim = true, bool ignoreEmpty = true}) { - if (s == null) return []; + if (s == null) { + return []; + } else if (s is String) { + return _toFlatListOfStringsFromString( + s, delimiter ?? _toListOfStringsDelimiter, trim, ignoreEmpty); + } else if (s is Iterable) { + return _toFlatListOfStringsFromIterable( + s, delimiter ?? _toListOfStringsDelimiter, trim, ignoreEmpty); + } else { + return _toFlatListOfStringsFromString( + '$s', delimiter ?? _toListOfStringsDelimiter, trim, ignoreEmpty); + } +} + +List _toFlatListOfStringsFromString( + String s, Pattern delimiter, bool trim, bool ignoreEmpty) { + var list = s.split(delimiter); - delimiter ??= _toListOfStringsDelimiter; + if (trim) { + trimListOfStrings(list); + } - List list; + if (ignoreEmpty) { + list.removeWhere((e) => e.isEmpty); + } - if (s is String) { - list = s.split(delimiter); - } else if (s is Iterable) { - list = []; - - for (var e in s) { - if (e == null) continue; - - if (e is String) { - var l2 = toFlatListOfStrings(e, - delimiter: delimiter, trim: trim, ignoreEmpty: ignoreEmpty); - list.addAll(l2); - } else if (e is Iterable) { - var l2 = toFlatListOfStrings(e, - delimiter: delimiter, trim: trim, ignoreEmpty: ignoreEmpty); - list.addAll(l2); - } else { - var str = '$e'; - var l2 = toFlatListOfStrings(str, - delimiter: delimiter, trim: trim, ignoreEmpty: ignoreEmpty); - list.addAll(l2); - } + return list; +} + +List _toFlatListOfStringsFromIterable( + Iterable s, Pattern delimiter, bool trim, bool ignoreEmpty) { + var list = []; + + for (var e in s) { + if (e == null) continue; + + if (e is String) { + var l2 = _toFlatListOfStringsFromString(e, delimiter, trim, ignoreEmpty); + list.addAll(l2); + } else if (e is Iterable) { + var l2 = + _toFlatListOfStringsFromIterable(e, delimiter, trim, ignoreEmpty); + list.addAll(l2); + } else { + var l2 = + _toFlatListOfStringsFromString('$e', delimiter, trim, ignoreEmpty); + list.addAll(l2); } - } else { - list = []; } + if (list.isEmpty) return list; + if (trim) { - for (var i = 0; i < list.length; ++i) { - var e = list[i]; - var e2 = e.trim(); - if (e2.length != e.length) { - list[i] = e2; - } - } + trimListOfStrings(list); } - list.removeWhere((e) => (ignoreEmpty && e.isEmpty)); + if (ignoreEmpty) { + list.removeWhere((e) => e.isEmpty); + } return list; } +/// Apply [String.trim] to each [String] of [list]. +/// Returns the same [list] instance without change it's length. +List trimListOfStrings(List list) { + final length = list.length; + for (var i = 0; i < length; ++i) { + var e = list[i]; + var e2 = e.trim(); + if (e2.length != e.length) { + list[i] = e2; + } + } + return list; +} + /// Returns [true] if [list] elements are all of type [String]. bool isListOfString(Iterable? list) { if (list == null) return false; @@ -978,7 +1007,9 @@ bool isMapOfStringKeysAndListValues(Map? map) { if (map.isEmpty) return false; if (listNotMatchesAll( - map.entries, (e) => (e.key is String) && (e.value is List))) return false; + map.entries, (e) => (e.key is String) && (e.value is List))) { + return false; + } return true; } @@ -990,7 +1021,9 @@ bool isMapOfStringKeysAndNumValues(Map? map) { if (map.isEmpty) return false; if (listNotMatchesAll( - map.entries, (e) => (e.key is String) && (e.value is num))) return false; + map.entries, (e) => (e.key is String) && (e.value is num))) { + return false; + } return true; } @@ -2517,22 +2550,20 @@ class TreeReferenceMap implements Map { } /// Returns [true] if [key] is valid (in the tree). - bool isValidEntry(K key, V value) { - return isInTree(key); - } + bool isValidEntry(K key, V value) => isInTree(key); /// Returns [true] if [key] is in the tree. bool isInTree(K? key) { - if (key == null) return false; if (identical(root, key)) return true; - var cursor = key; - while (true) { + K? cursor = key; + while (cursor != null) { var parent = getParentOf(cursor); - if (parent == null) return false; if (identical(parent, root)) return true; cursor = parent; } + + return false; } /// Returns the parent of [key]. @@ -2704,9 +2735,11 @@ class TreeReferenceMap implements Map { /// Removed purged entries over [maxPurgedEntries] limit. void checkPurgeEntriesLimit() { - if (_purged != null && maxPurgedEntries != null && maxPurgedEntries! > 0) { - var purged = _purged!; - var needToRemove = purged.length - maxPurgedEntries!; + var purged = _purged; + var maxPurgedEntries = this.maxPurgedEntries; + + if (purged != null && maxPurgedEntries != null && maxPurgedEntries > 0) { + var needToRemove = purged.length - maxPurgedEntries; if (needToRemove > 0) { var del = []; for (var k in purged.keys) { @@ -2726,16 +2759,18 @@ class TreeReferenceMap implements Map { /// Remove expired purged entries. Only relevant if [purgedEntriesTimeout] is not null. void checkPurgedEntriesTimeout() { - if (_purged != null && + var purged = _purged; + var purgedEntriesTimeout = this.purgedEntriesTimeout; + + if (purged != null && purgedEntriesTimeout != null && - purgedEntriesTimeout!.inMilliseconds > 0) { - var purged = _purged!; - var timeoutMs = purgedEntriesTimeout!.inMilliseconds; + purgedEntriesTimeout.inMilliseconds > 0) { + var timeoutMs = purgedEntriesTimeout.inMilliseconds; var now = DateTime.now().millisecondsSinceEpoch; var expired = purged.entries .where((e) => (now - e.value.key.millisecondsSinceEpoch) > timeoutMs) .map((e) => e.key) - .toList(); + .toList(growable: false); if (expired.isNotEmpty) { for (var k in expired) { @@ -2752,24 +2787,28 @@ class TreeReferenceMap implements Map { /// Restore purged entries that are currently valid. Only relevant if [keepPurgedEntries] is true. int revalidatePurgedEntries() { - if (_purged != null) { - var purged = _purged!; - var validPurged = purged.entries - .where((e) => isValidEntry(e.key, e.value.value)) - .toList(); - - if (validPurged.isNotEmpty) { - for (var e in validPurged) { - _map[e.key] = e.value.value; - purged.remove(e.key); - } - _expireCache(); + var purged = _purged; + if (purged == null) return 0; + + var revalidateCount = 0; + + purged.removeWhere((k, v) { + var value = v.value; + if (isValidEntry(k, value)) { + ++revalidateCount; + _map[k] = value; + return true; + } else { + return false; } + }); - _revalidatedPurgedEntriesCount += validPurged.length; - return validPurged.length; + if (revalidateCount > 0) { + _expireCache(); } - return 0; + + _revalidatedPurgedEntriesCount += revalidateCount; + return revalidateCount; } /// Returns the valid entries. @@ -2781,12 +2820,12 @@ class TreeReferenceMap implements Map { _map.entries.where((e) => !isValidEntry(e.key, e.value)).toList(); /// Returns the purged entries. Only relevant if [keepPurgedEntries] is true. - List> get purgedEntries => _purged != null - ? _purged!.entries.map((e) => MapEntry(e.key, e.value.value)).toList() - : >[]; + List> get purgedEntries => + _purged?.entries.map((e) => MapEntry(e.key, e.value.value)).toList() ?? + >[]; /// Returns the purged keys. Only relevant if [keepPurgedEntries] is true. - List get purgedKeys => _purged != null ? _purged!.keys.toList() : []; + List get purgedKeys => _purged?.keys.toList() ?? []; /// Returns the valid keys. List get validKeys => _map.entries @@ -2807,7 +2846,6 @@ class TreeReferenceMap implements Map { R? _walkTreeImpl(K node, R Function(K node) walker) { var children = getChildrenOf(node); - if (children.isEmpty) return null; for (var child in children) { R? ret = walker(child); @@ -2879,17 +2917,17 @@ class TreeReferenceMap implements Map { /// Returns [keys] reversed (unmodifiable); List get keysReversed { - _keysReversedList ??= _map.keys.toList().reversed.toList(); - return UnmodifiableListView(_keysReversedList!); + var keys = _keysReversedList ??= _map.keys.toList().reversed.toList(); + return UnmodifiableListView(keys); } List? _purgedKeysReversedList; /// Returns [purgedKeys] reversed (unmodifiable); List get purgedKeysReversed { - _purgedKeysReversedList ??= - _purged != null ? _purged!.keys.toList().reversed.toList() : []; - return UnmodifiableListView(_purgedKeysReversedList!); + var keys = _purgedKeysReversedList ??= + _purged?.keys.toList().reversed.toList() ?? []; + return UnmodifiableListView(keys); } void _expireCache() { diff --git a/lib/src/date.dart b/lib/src/date.dart index 3d7b2cc..51eca23 100644 --- a/lib/src/date.dart +++ b/lib/src/date.dart @@ -435,8 +435,6 @@ int? getDateTimeWeekDayIndex(DateTimeWeekDay? weekDay) { return 6; case DateTimeWeekDay.sunday: return 7; - default: - return null; } } @@ -747,8 +745,6 @@ Pair getDateTimeRange(DateRangeType rangeType, return getDateTimeLastMonth(time); case DateRangeType.thisMonth: return getDateTimeThisMonth(time); - default: - throw UnsupportedError("Can't handle: $rangeType"); } } diff --git a/pubspec.yaml b/pubspec.yaml index a04e3e4..acaed1d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,21 +1,21 @@ name: swiss_knife description: Dart Useful Tools - collections, math, date, uri, json, events, resources, regexp, etc... -version: 3.2.2 +version: 3.2.3 homepage: https://github.com/gmpassos/swiss_knife environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: intl: ^0.19.0 resource_portable: ^3.1.0 dev_dependencies: - lints: ^3.0.0 - test: ^1.25.8 - dependency_validator: ^3.2.3 + lints: ^4.0.0 + test: ^1.25.14 + dependency_validator: ^4.1.2 collection: ^1.18.0 - coverage: ^1.9.2 + coverage: ^1.11.1 #dependency_overrides: # resource_portable: diff --git a/test/swiss_knife_test.dart b/test/swiss_knife_test.dart index a16145b..d208eaf 100644 --- a/test/swiss_knife_test.dart +++ b/test/swiss_knife_test.dart @@ -1322,6 +1322,22 @@ void main() { toFlatListOfStrings([' a ', ' b ', 'c_d'], delimiter: '_', trim: false), equals([' a ', ' b ', 'c', 'd'])); + + expect( + toFlatListOfStrings([ + 1, + DateTime.utc(2000, 1, 1, 1, 1, 1, 1, 1), + [ + 2, + 3, + [4, [], 5] + ] + ]), + equals(['1', '2000-01-01', '01:01:01.001001Z', '2', '3', '4', '5'])); + }); + + test('trimListOfStrings', () { + expect(trimListOfStrings([' a ', 'b', ' ']), equals(['a', 'b', ''])); }); test('listMatchesAll/listNotMatchesAll', () {