From dcd878023e795881df452b2b061ec132340808f5 Mon Sep 17 00:00:00 2001 From: windrunner Date: Fri, 17 Sep 2021 22:48:30 +0800 Subject: [PATCH 1/4] Add List.getOrNull extension --- lib/src/list_extensions.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/list_extensions.dart b/lib/src/list_extensions.dart index f61d610..17bf6d9 100644 --- a/lib/src/list_extensions.dart +++ b/lib/src/list_extensions.dart @@ -252,6 +252,10 @@ extension ListExtensions on List { } return true; } + + /// Returns an element at the given [index] + /// or `null` if the [index] is out of bounds of this list. + E? getOrNull(int index) => (index >= 0 && index < length) ? this[index] : null; } /// Various extensions on lists of comparable elements. From 55eb40c89fddc753603d5d4fe857754221893525 Mon Sep 17 00:00:00 2001 From: Yuxiang Liu Date: Mon, 20 Dec 2021 01:18:52 +0800 Subject: [PATCH 2/4] add elementAtOrNull(int index) --- lib/src/iterable_extensions.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/src/iterable_extensions.dart b/lib/src/iterable_extensions.dart index fae5f8e..9220527 100644 --- a/lib/src/iterable_extensions.dart +++ b/lib/src/iterable_extensions.dart @@ -352,6 +352,11 @@ extension IterableExtension on Iterable { } return null; } + + /// Returns an element at the given [index] + /// or `null` if the [index] is out of bounds of this list. + /// [index] must not be negative + T? elementAtOrNull(int index) => skip(index).firstOrNull; /// Groups elements by [keyOf] then folds the elements in each group. /// From 5d8d54436830c164f357e4b0b0801378bafe9293 Mon Sep 17 00:00:00 2001 From: Yuxiang Liu Date: Mon, 20 Dec 2021 01:25:15 +0800 Subject: [PATCH 3/4] remove getOrNull and add elementAtOrNull --- lib/src/list_extensions.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/list_extensions.dart b/lib/src/list_extensions.dart index 17bf6d9..2260048 100644 --- a/lib/src/list_extensions.dart +++ b/lib/src/list_extensions.dart @@ -255,7 +255,8 @@ extension ListExtensions on List { /// Returns an element at the given [index] /// or `null` if the [index] is out of bounds of this list. - E? getOrNull(int index) => (index >= 0 && index < length) ? this[index] : null; + /// [index] must not be negative + T? elementAtOrNull(int index) => (index < length) ? this[index] : null; } /// Various extensions on lists of comparable elements. From 3abc0a8f7960e7ae570d89ba495432f6f3f43502 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 26 May 2022 23:17:31 +0000 Subject: [PATCH 4/4] Update docs, bump version, add tests --- CHANGELOG.md | 4 +++- lib/src/iterable_extensions.dart | 14 ++++++++++---- lib/src/list_extensions.dart | 15 +++++++++++---- pubspec.yaml | 2 +- test/extensions_test.dart | 29 +++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 806a8b0..9ee21bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -## 1.16.1-dev +## 1.17.0-dev + +* Add `Iterable.elementAtOrNull` and `List.elementAtOrNull` extension methods. ## 1.16.0 diff --git a/lib/src/iterable_extensions.dart b/lib/src/iterable_extensions.dart index c115bd3..71d6dc8 100644 --- a/lib/src/iterable_extensions.dart +++ b/lib/src/iterable_extensions.dart @@ -352,10 +352,16 @@ extension IterableExtension on Iterable { } return null; } - - /// Returns an element at the given [index] - /// or `null` if the [index] is out of bounds of this list. - /// [index] must not be negative + + /// The [index]th element, or `null` if there is no such element. + /// + /// Returns the element at position [index] of this iterable, + /// just like [elementAt], if this iterable has such an element. + /// If this iterable does not have enough elements to have one with the given + /// [index], the `null` value is returned, unlike [elementAt] which throws + /// instead. + /// + /// The [index] must not be negative. T? elementAtOrNull(int index) => skip(index).firstOrNull; /// Groups elements by [keyOf] then folds the elements in each group. diff --git a/lib/src/list_extensions.dart b/lib/src/list_extensions.dart index 9f67265..4bb719a 100644 --- a/lib/src/list_extensions.dart +++ b/lib/src/list_extensions.dart @@ -258,10 +258,17 @@ extension ListExtensions on List { } return true; } - /// Returns an element at the given [index] - /// or `null` if the [index] is out of bounds of this list. - /// [index] must not be negative - T? elementAtOrNull(int index) => (index < length) ? this[index] : null; + + /// The [index]th element, or `null` if there is no such element. + /// + /// Returns the element at position [index] of this list, + /// just like [elementAt], if this list has such an element. + /// If this list does not have enough elements to have one with the given + /// [index], the `null` value is returned, unlike [elementAt] which throws + /// instead. + /// + /// The [index] must not be negative. + E? elementAtOrNull(int index) => (index < length) ? this[index] : null; /// Contiguous [slice]s of [this] with the given [length]. /// diff --git a/pubspec.yaml b/pubspec.yaml index 436a1e1..07a5fa1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: collection -version: 1.16.1-dev +version: 1.17.0-dev description: Collections and utilities functions and classes related to collections. repository: https://github.com/dart-lang/collection diff --git a/test/extensions_test.dart b/test/extensions_test.dart index 1ccebde..167dc5b 100644 --- a/test/extensions_test.dart +++ b/test/extensions_test.dart @@ -1141,6 +1141,21 @@ void main() { } }); }); + group('.elementAtOrNull', () { + test('empty', () async { + expect(iterable([]).elementAtOrNull(0), isNull); + }); + test('negative index', () async { + expect(() => iterable([1]).elementAtOrNull(-1), + throwsA(isA())); + }); + test('index within range', () async { + expect(iterable([1]).elementAtOrNull(0), 1); + }); + test('index too high', () async { + expect(iterable([1]).elementAtOrNull(1), isNull); + }); + }); group('.slices', () { test('empty', () { expect(iterable([]).slices(1), []); @@ -1729,6 +1744,20 @@ void main() { ['1', 'b']); }); }); + group('.elementAtOrNull', () { + test('empty', () async { + expect([].elementAtOrNull(0), isNull); + }); + test('negative index', () async { + expect(() => [1].elementAtOrNull(-1), throwsA(isA())); + }); + test('index within range', () async { + expect([1].elementAtOrNull(0), 1); + }); + test('index too high', () async { + expect([1].elementAtOrNull(1), isNull); + }); + }); group('.slices', () { test('empty', () { expect([].slices(1), []);