├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── dart_build.yml
├── .gitignore
├── .metadata
├── .vscode
└── launch.json
├── AUTHORS
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── example
├── .gitignore
├── README.md
├── bin
│ ├── main.dart
│ └── src
│ │ ├── iterable.common.examples.dart
│ │ ├── iterable.comparable.examples.dart
│ │ ├── iterable.math.examples.dart
│ │ ├── iterable.set.examples.dart
│ │ └── pet.model.dart
└── pubspec.yaml
├── lib
├── flinq.dart
└── src
│ ├── iterable.common.extension.dart
│ ├── iterable.comparable.extension.dart
│ ├── iterable.math.extension.dart
│ └── iterable.set.extension.dart
├── publish_commands.txt
├── pubspec.lock
├── pubspec.yaml
└── test
├── flinq_test.dart
└── src
├── iterable.common.test.dart
├── iterable.comparable.test.dart
├── iterable.math.test.dart
└── iterable.set.test.dart
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: I have a problem with my Flutter application.
3 | about: You are writing an application with Flutter but the application is crashing
4 | or throws an exception, a widget is buggy, or something looks wrong.
5 | title: ''
6 | labels: ''
7 | assignees: ''
8 |
9 | ---
10 |
11 |
23 |
24 | ## Steps to Reproduce
25 |
26 |
27 |
28 | 1. Run `flutter create bug`.
29 | 2. Update the files as follows: ...
30 | 3. ...
31 |
32 | **Expected results:**
33 |
34 | **Actual results:**
35 |
36 |
37 | Logs
38 |
39 |
45 |
46 | ```
47 | ```
48 |
49 |
53 |
54 | ```
55 | ```
56 |
57 |
58 |
59 | ```
60 | ```
61 |
62 |
63 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a new idea for Flutter.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
22 |
23 | ## Use case
24 |
25 |
35 |
36 | ## Proposal
37 |
38 |
47 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | *Replace this paragraph with a description of what this PR is doing. If you're modifying existing behavior, describe the existing behavior, how this PR is changing it, and what motivated the change. If you're changing visual properties, consider including before/after screenshots (and runnable code snippets to reproduce them).*
4 |
5 | ## Related Issues
6 |
7 | *Replace this paragraph with a list of issues related to this PR from our issue database. Indicate, which of these issues are resolved or fixed by this PR. There should be at least one issue listed here.*
8 |
9 | ## Tests
10 |
11 | I added the following tests:
12 |
13 | *Replace this with a list of the tests that you added as part of this PR. A change in behaviour with no test covering it
14 | will likely get reverted accidentally sooner or later. PRs must include tests for all changed/updated/fixed behaviors. See [Test Coverage].*
15 |
16 | ## Checklist
17 |
18 | Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (`[x]`). This will ensure a smooth and quick review process.
19 |
20 | - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
21 | - [ ] I updated/added relevant documentation (doc comments with `///`).
22 | - [ ] All existing and new tests are passing.
23 | - [ ] The analyzer (`flutter analyze --flutter-repo`) does not report any problems on my PR.
24 | - [ ] I am willing to follow-up on review comments in a timely manner.
25 |
26 | ## Breaking Change
27 |
28 | Did any tests fail when you ran them?
29 |
30 | - [ ] No, no existing tests failed, so this is *not* a breaking change.
31 | - [ ] Yes, this is a breaking change. *If not, delete the remainder of this section.*
32 | - [ ] I wrote a design doc: https://flutter.dev/go/template *Replace this with a link to your design doc's short link*
33 | - [ ] I got input from the developer relations team, specifically from: *Replace with the names of who gave advice*
34 | - [ ] I wrote a migration guide: *Replace with a link to your migration guide*
35 |
36 |
37 | [Test Coverage]: https://github.com/flutter/flutter/wiki/Test-coverage-for-package%3Aflutter
38 | [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
39 | [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
40 |
--------------------------------------------------------------------------------
/.github/workflows/dart_build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - develop
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | container:
15 | image: google/dart:latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 |
20 | - name: Install dependencies
21 | run: pub get
22 |
23 | - name: Run tests
24 | run: pub run test
25 |
26 | - name: Activate coverage package
27 | run: pub global activate coverage
28 |
29 | - name: Collect coverage in json
30 | run: dart --disable-service-auth-codes --enable-vm-service=8111 --pause-isolates-on-exit test/flinq_test.dart & nohup pub global run coverage:collect_coverage --port=8111 --out=coverage.json --wait-paused --resume-isolates
31 |
32 | - name: Convert coverage to lcov
33 | run: pub global run coverage:format_coverage --lcov --in=coverage.json --out=lcov.info --packages=.packages --report-on=lib
34 |
35 | - name: Upload coverage to Codecov
36 | uses: codecov/codecov-action@v1.0.5
37 | with:
38 | token: ${{ secrets.CODECOV_TOKEN }}
39 | flags: unittests
40 | file: ./lcov.info
41 | name: codecov-flinq
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .packages
28 | .pub-cache/
29 | .pub/
30 | build/
31 |
32 | # Android related
33 | **/android/**/gradle-wrapper.jar
34 | **/android/.gradle
35 | **/android/captures/
36 | **/android/gradlew
37 | **/android/gradlew.bat
38 | **/android/local.properties
39 | **/android/**/GeneratedPluginRegistrant.java
40 |
41 | # iOS/XCode related
42 | **/ios/**/*.mode1v3
43 | **/ios/**/*.mode2v3
44 | **/ios/**/*.moved-aside
45 | **/ios/**/*.pbxuser
46 | **/ios/**/*.perspectivev3
47 | **/ios/**/*sync/
48 | **/ios/**/.sconsign.dblite
49 | **/ios/**/.tags*
50 | **/ios/**/.vagrant/
51 | **/ios/**/DerivedData/
52 | **/ios/**/Icon?
53 | **/ios/**/Pods/
54 | **/ios/**/.symlinks/
55 | **/ios/**/profile
56 | **/ios/**/xcuserdata
57 | **/ios/.generated/
58 | **/ios/Flutter/App.framework
59 | **/ios/Flutter/Flutter.framework
60 | **/ios/Flutter/Flutter.podspec
61 | **/ios/Flutter/Generated.xcconfig
62 | **/ios/Flutter/app.flx
63 | **/ios/Flutter/app.zip
64 | **/ios/Flutter/flutter_assets/
65 | **/ios/Flutter/flutter_export_environment.sh
66 | **/ios/ServiceDefinitions.json
67 | **/ios/Runner/GeneratedPluginRegistrant.*
68 |
69 | # Exceptions to above rules.
70 | !**/ios/**/default.mode1v3
71 | !**/ios/**/default.mode2v3
72 | !**/ios/**/default.pbxuser
73 | !**/ios/**/default.perspectivev3
74 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
75 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 856a90e67c9284124d44d2be6c785bacd3a1c772
8 | channel: dev
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Example CMD",
9 | "program": "example/bin/main.dart",
10 | "request": "launch",
11 | "type": "dart"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # Below is a list of people and organizations that have contributed
2 | # to the MarchDev Toolkit projects. Names should be added to the list like so:
3 | #
4 | # Name/Organization
5 |
6 | MarchDev Toolkit
7 | - Oleh Marchenko
8 | - Elena Marchenko
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 2.0.2
4 |
5 | * Updated docs due to changes in `singleOrNull` and `singleOrNullWhere` API
6 | * Fixed tests for `singleOrNull` and `singleOrNullWhere`
7 |
8 | ## 2.0.1
9 |
10 | * Added collection dependency
11 |
12 | ## 2.0.0
13 |
14 | * Updated to NNBD
15 |
16 | ## 1.1.1
17 |
18 | * Update docs
19 |
20 | ## 1.1.0
21 |
22 | * Moved `group` and `groupMap` to common extensions
23 |
24 | ## 1.0.0
25 |
26 | * Added `distinctWhere`, `unionWhere`, `intersectionWhere`, `differenceWhere` extensions
27 | * Added `minWhere`, `maxWhere`, `minOrNullWhere`, `maxOrNullWhere` extensions
28 |
29 | ## 0.5.0
30 |
31 | * Added `whereList`, `whereMapList`, `mapWhereList`, `notNull` extensions
32 | * Added `sumWhere`, `averageWhere` extensions
33 | * Redo examples
34 |
35 | ## 0.4.1
36 |
37 | * Migrated to GitHub
38 | * Minor refactorings
39 | * Updated homepage link
40 |
41 | ## 0.4.0
42 |
43 | * Added group and groupMap methods
44 | * Updated example
45 |
46 | ## 0.3.0
47 |
48 | * Added tests
49 | * Updated README
50 |
51 | ## 0.2.0
52 |
53 | * Moved `List` `set` extensions to `Iterable` `set` extensions
54 | * Moved `List` `common` extensions to `Iterable` `common` extensions
55 | * Added examples
56 |
57 | ## 0.1.0
58 |
59 | * Created `Iterable` `common` extensions
60 | * Created `Iterable` `comparable` extensions
61 | * Created `Iterable` `math` extensions
62 | * Created `List` `common` extensions
63 | * Created `List` `set` extensions
64 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at eo.march.dev+support@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md and CHANGELOG.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this
15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16 | 4. You may merge the Pull Request in once you have the sign-off of one other developer, or if you
17 | do not have permission to do that, you may request the second reviewer to merge it for you.
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, MarchDev Toolkit
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flinq
2 |
3 | 
4 | [](https://codecov.io/gh/marchdev-tk/flinq)
5 | [](https://pub.dartlang.org/packages/flinq)
6 | 
7 | 
8 |
9 | Extended capabilities for collections.
10 | It's a bunch of shortcuts to avoid unnecesary boilerplate work with collections.
11 |
12 | ## Getting Started
13 |
14 | This package will help you to reduce the amount of boilerplate code by adding folowing extensions for `Iterable`s:
15 |
16 | * getter `firstOrNull` and method `firstOrNullWhere` for getting first value, and if it will not be found returns `null`
17 |
18 | * getter `lastOrNull` and method `lastOrNullWhere` for getting last value, and if it will not be found returns `null`
19 |
20 | * getter `singleOrNull` and method `singleOrNullWhere` for getting single value, and if it will not be found returns `null`, and if there will be too many elements it'll also return `null`
21 |
22 | * method `mapList`, which maps collection and casts it to `List`
23 |
24 | * method `whereList`, which filters collection and casts it to `List`
25 |
26 | * method `mapWhereList`, which maps collection, then filters it and then casts it to `List`
27 |
28 | * method `whereMapList`, which filters collection, then maps collection and then casts it to `List`
29 |
30 | * getter `notNull` for getting only **not null** values from the collection
31 |
32 | * method `group` and `groupMap` for grouping a collection
33 |
34 | * getter `min`/`minOrNull` and `max`/`maxOrNull` for getting minimal or maximal value from collection of `Comparable`s
35 |
36 | * method `minWhere`/`minOrNullWhere` and `maxWhere`/`maxOrNullWhere` for getting minimal or maximal value from filtered collection of `Comparable`s
37 |
38 | * getter `sum` and `average` for getting sum and average from collection of `num`s
39 |
40 | * method `sumWhere` and `averageWhere` for getting sum and average from filtered collection of `num`s
41 |
42 | * getter `distinct` and method `distinctWhere` which will return `List` with unique values in collection
43 |
44 | * method `union` and `unionWhere` which will return `List` with union of two collections with only unique values in resulting collection
45 |
46 | * method `intersection` and `intersectionWhere` which will return `List` with elements that contains both collections with only unique values in resulting collection
47 |
48 | * method `difference` and `differenceWhere` which will return `List` with difference between two collections with only unique values in resulting collection
49 |
50 | ## Examples
51 |
52 | `Iterable` extension can be used like this:
53 |
54 | ### Common
55 |
56 | * **firstOrNull** and **firstOrNullWhere**
57 |
58 | ```dart
59 | final firstOrNull = [].firstOrNull; // null
60 | // or
61 | final firstOrNull = [3, 6, 2, 7, 9].firstOrNullWhere((item) => item > 10); // null
62 | ```
63 |
64 | * **lastOrNull** and **lastOrNullWhere**
65 |
66 | ```dart
67 | final lastOrNull = [].lastOrNull; // null
68 | // or
69 | final lastOrNull = [3, 6, 2, 7, 9].lastOrNullWhere((item) => item > 10); // null
70 | ```
71 |
72 | * **singleOrNull** and **singleOrNullWhere**
73 |
74 | ```dart
75 | final singleOrNull = [].singleOrNull; // null
76 | // or
77 | final singleOrNull = [3, 6, 2, 7, 9].singleOrNullWhere((item) => item > 3); // null
78 | ```
79 |
80 | * **mapList**
81 |
82 | ```dart
83 | List mappedList = [3, 6, 2, 7, 9].mapList((item) => item.toDouble());
84 | ```
85 |
86 | * **whereList**
87 |
88 | ```dart
89 | List filteredList = [3, 6, 2, 7, 9].whereList((item) => item > 4);
90 | ```
91 |
92 | * **whereMapList**
93 |
94 | ```dart
95 | List filteredMappedList = [3, 6, 2, 7, 9].whereMapList((item) => item > 4, (item) => item.toDouble());
96 | ```
97 |
98 | * **mapWhereList**
99 |
100 | ```dart
101 | List mappedFilteredList = [3, 6, 2, 7, 9].mapWhereList((item) => item.toDouble(), (item) => item > 4);
102 | ```
103 |
104 | * **notNull**
105 |
106 | ```dart
107 | Iterable notNullIterable = [3, 6, 2, null, 7, 9].notNull;
108 | ```
109 |
110 | * **group**
111 |
112 | ```dart
113 | final collection = [
114 | Pet("rat", "Mike"),
115 | Pet("dog", "Rex"),
116 | Pet("cat", "Lucy"),
117 | ];
118 |
119 | /*
120 | >{
121 | true: [
122 | Pet("rat", "Mike"),
123 | Pet("cat", "Lucy"),
124 | ],
125 | false: [
126 | Pet("dog", "Rex"),
127 | ],
128 | }
129 | */
130 | final group = collection.group((item) => item.name.endsWith('at'));
131 | ```
132 |
133 | * **groupMap**
134 |
135 | ```dart
136 | final collection = [
137 | Pet("rat", "Mike"),
138 | Pet("dog", "Rex"),
139 | Pet("cat", "Lucy"),
140 | ];
141 |
142 | /*
143 | {
144 | true: 2,
145 | false: 1,
146 | }
147 | */
148 | final groupMapped = collection.groupMap(
149 | (item) => item.name.endsWith('at'), (group) => group.length);
150 | ```
151 |
152 | ### Comparable
153 |
154 | * **min** and **minOrNull**
155 |
156 | ```dart
157 | final min = [3, 6, 2, 7, 9].min; // 2
158 | // or
159 | final min = [].minOrNull; // null
160 | ```
161 |
162 | * **minWhere** and **minOrNullWhere**
163 |
164 | ```dart
165 | final min = [3, 6, 2, 7, 9].minWhere((_) => _ > 4); // 6
166 | // or
167 | final min = [3, 2].minOrNullWhere((_) => _ > 4); // null
168 | ```
169 |
170 | * **max** and **maxOrNull**
171 |
172 | ```dart
173 | final max = [3, 6, 2, 7, 9].max; // 9
174 | // or
175 | final max = [].maxOrNull; // null
176 | ```
177 |
178 | * **maxWhere** and **maxOrNullWhere**
179 |
180 | ```dart
181 | final max = [3, 6, 2, 7, 9].maxWhere((_) => _ < 4); // 3
182 | // or
183 | final max = [3, 2].maxOrNullWhere((_) => _ > 4); // null
184 | ```
185 |
186 | ### Math
187 |
188 | * **sum**
189 |
190 | ```dart
191 | final sum = [3, 6, 2, 7, 9].sum; // 27
192 | ```
193 |
194 | * **average**
195 |
196 | ```dart
197 | final average = [1, 3, 5, 7, 4, 4].average; // 4
198 | ```
199 |
200 | * **sumWhere**
201 |
202 | ```dart
203 | final sum = [3, 6, 2, 7, 9].sumWhere((_) => _ > 4); // 22
204 | ```
205 |
206 | * **averageWhere**
207 |
208 | ```dart
209 | final average = [1, 3, 5, 7, 4, 4].averageWhere((_) => _ > 4); // 6
210 | ```
211 |
212 | ### Set
213 |
214 | * **distinct**
215 |
216 | ```dart
217 | final collectionOne = [2, 5, 8, 2];
218 |
219 | final distinctCollection = collectionOne.distinct; // [2, 5, 8]
220 | ```
221 |
222 | * **distinctWhere**
223 |
224 | ```dart
225 | final collectionOne = [2, 5, 8, 2];
226 |
227 | final distinctCollection = collectionOne.distinctWhere((_) => _ > 4); // [5, 8]
228 | ```
229 |
230 | * **union**
231 |
232 | ```dart
233 | final collectionOne = [2, 5, 8, 2];
234 | final collectionTwo = [1, 3, 5, 7];
235 |
236 | final unitedCollection = collectionOne.union(collectionTwo); // [2, 5, 8, 1, 3, 7]
237 | ```
238 |
239 | * **unionWhere**
240 |
241 | ```dart
242 | final collectionOne = [2, 5, 8, 2];
243 | final collectionTwo = [1, 3, 5, 7];
244 |
245 | final unitedCollection = collectionOne.unionWhere(collectionTwo, (_) => _ > 4); // [5, 8, 7]
246 | ```
247 |
248 | * **intersection**
249 |
250 | ```dart
251 | final collectionOne = [2, 5, 8, 2];
252 | final collectionTwo = [1, 3, 5, 7];
253 |
254 | final intersectedCollection = collectionOne.intersection(collectionTwo); // [5]
255 | ```
256 |
257 | * **intersectionWhere**
258 |
259 | ```dart
260 | final collectionOne = [2, 5, 8, 2];
261 | final collectionTwo = [1, 3, 5, 7];
262 |
263 | final intersectedCollection = collectionOne.intersectionWhere(collectionTwo, (_) => _ < 4); // []
264 | ```
265 |
266 | * **difference**
267 |
268 | ```dart
269 | final collectionOne = [2, 5, 8, 2];
270 | final collectionTwo = [1, 3, 5, 7];
271 |
272 | final differedCollection = collectionOne.difference(collectionTwo); // [2, 8]
273 | // or
274 | final differedCollection = collectionTwo.difference(collectionOne); // [1, 3, 7]
275 | ```
276 |
277 | * **differenceWhere**
278 |
279 | ```dart
280 | final collectionOne = [2, 5, 8, 2];
281 | final collectionTwo = [1, 3, 5, 7];
282 |
283 | final differedCollection = collectionOne.differenceWhere(collectionTwo, (_) => _ < 4); // [2]
284 | // or
285 | final differedCollection = collectionTwo.differenceWhere(collectionOne, (_) => _ < 4); // [1, 3]
286 | ```
287 |
288 | ## Feature requests and Bug reports
289 |
290 | Feel free to post a feature requests or report a bug [here](https://github.com/marchdev-tk/flinq/issues).
291 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # Defines a default set of lint rules enforced for
2 | # projects at Google. For details and rationale,
3 | # see https://github.com/dart-lang/pedantic#enabled-lints.
4 | include: package:pedantic/analysis_options.1.8.0.yaml
5 |
6 | # For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
7 | # Uncomment to specify additional rules.
8 | # linter:
9 | # rules:
10 | # - camel_case_types
11 |
12 | # analyzer:
13 | # exclude:
14 | # - path/to/excluded/files/**
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Files and directories created by pub
2 | .dart_tool/
3 | .packages
4 | # Remove the following pattern if you wish to check in your lock file
5 | pubspec.lock
6 |
7 | # Conventional directory for build outputs
8 | build/
9 |
10 | # Directory created by dartdoc
11 | doc/api/
12 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # flinq_example
2 |
3 | Demonstrates how to use the flinq package.
4 |
5 | ## Usage
6 |
7 | ### Pet model
8 |
9 | ```dart
10 | class Pet implements Comparable {
11 | const Pet(this.name, this.nickname);
12 |
13 | final String name;
14 | final String nickname;
15 |
16 | @override
17 | int compareTo(Pet other) => name.compareTo(other.name);
18 |
19 | @override
20 | bool operator ==(Object other) =>
21 | other is Pet ? other.name == name && other.nickname == nickname : false;
22 |
23 | @override
24 | int get hashCode => name.hashCode + nickname.hashCode;
25 |
26 | @override
27 | String toString() => '$name ($nickname)';
28 | }
29 | ```
30 |
31 | ### Iterable Common
32 |
33 | ```dart
34 | final _emptyCollection = [];
35 | final _singleItemCollection = ["item"];
36 | final _numCollection = [3, 6, 2, 7, 9];
37 | final _comparableCollection = [
38 | Pet("rat", "Mike"),
39 | Pet("dog", "Rex"),
40 | Pet("cat", "Lucy"),
41 | ];
42 |
43 | void _firstOrNull() {
44 | print('---- firstOrNull ----\n');
45 |
46 | var result = _emptyCollection.firstOrNull; // []
47 | assert(result == null); // true
48 | print(result?.toString());
49 |
50 | result = _singleItemCollection.firstOrNull; // ["item"]
51 | assert(result == "item"); // true
52 | print(result?.toString());
53 |
54 | result = _numCollection.firstOrNull; // [3, 6, 2, 7, 9]
55 | assert(result == 3); // true
56 | print(result?.toString());
57 |
58 | result = _comparableCollection
59 | .firstOrNull; // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
60 | assert(result == Pet("rat", "Mike")); // true
61 | print(result?.toString());
62 |
63 | print('---- ----------- ----\n');
64 | }
65 |
66 | void _lastOrNull() {
67 | print('---- lastOrNull ----\n');
68 |
69 | var result = _emptyCollection.lastOrNull; // []
70 | assert(result == null); // true
71 | print(result?.toString());
72 |
73 | result = _singleItemCollection.lastOrNull; // ["item"]
74 | assert(result == "item"); // true
75 | print(result?.toString());
76 |
77 | result = _numCollection.lastOrNull; // [3, 6, 2, 7, 9]
78 | assert(result == 9); // true
79 | print(result?.toString());
80 |
81 | result = _comparableCollection
82 | .lastOrNull; // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
83 | assert(result == Pet("cat", "Lucy")); // true
84 | print(result?.toString());
85 |
86 | print('---- ---------- ----\n');
87 | }
88 |
89 | void _singleOrNull() {
90 | print('---- singleOrNull ----\n');
91 |
92 | var result = _emptyCollection.singleOrNull; // []
93 | assert(result == null); // true
94 | print(result?.toString());
95 |
96 | result = _singleItemCollection.singleOrNull; // ["item"]
97 | assert(result == "item"); // true
98 | print(result?.toString());
99 |
100 | try {
101 | result = _numCollection.singleOrNull; // [3, 6, 2, 7, 9]
102 | assert(false);
103 | print(result?.toString());
104 | } catch (e) {
105 | assert(e is StateError); // true (Too many elements)
106 | print(e.toString());
107 | }
108 |
109 | try {
110 | result = _comparableCollection
111 | .singleOrNull; // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
112 | assert(false);
113 | print(result?.toString());
114 | } catch (e) {
115 | assert(e is StateError); // true (Too many elements)
116 | print(e.toString());
117 | }
118 |
119 | print('---- ------------ ----\n');
120 | }
121 |
122 | void _firstOrNullWhere() {
123 | print('---- firstOrNullWhere ----\n');
124 |
125 | var result = _emptyCollection.firstOrNullWhere((item) => item != null); // []
126 | assert(result == null); // true
127 | print(result?.toString());
128 |
129 | result = _singleItemCollection
130 | .firstOrNullWhere((item) => item != "item"); // ["item"]
131 | assert(result == null); // true
132 | print(result?.toString());
133 |
134 | result =
135 | _numCollection.firstOrNullWhere((item) => item > 3); // [3, 6, 2, 7, 9]
136 | assert(result == 6); // true
137 | print(result?.toString());
138 |
139 | result = _comparableCollection.firstOrNullWhere(
140 | (item) => item.name.contains("at"),
141 | ); // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
142 | assert(result == Pet("rat", "Mike")); // true
143 | print(result?.toString());
144 |
145 | print('---- ---------------- ----\n');
146 | }
147 |
148 | void _lastOrNullWhere() {
149 | print('---- lastOrNullWhere ----\n');
150 |
151 | var result = _emptyCollection.lastOrNullWhere((item) => item != null); // []
152 | assert(result == null); // true
153 | print(result?.toString());
154 |
155 | result = _singleItemCollection
156 | .lastOrNullWhere((item) => item != "item"); // ["item"]
157 | assert(result == null); // true
158 | print(result?.toString());
159 |
160 | result =
161 | _numCollection.lastOrNullWhere((item) => item > 3); // [3, 6, 2, 7, 9]
162 | assert(result == 9); // true
163 | print(result?.toString());
164 |
165 | result = _comparableCollection.lastOrNullWhere(
166 | (item) => item.name.contains("at"),
167 | ); // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
168 | assert(result == Pet("cat", "Lucy")); // true
169 | print(result?.toString());
170 |
171 | print('---- --------------- ----\n');
172 | }
173 |
174 | void _singleOrNullWhere() {
175 | print('---- singleOrNullWhere ----\n');
176 |
177 | var result = _emptyCollection.singleOrNullWhere((item) => item != null); // []
178 | assert(result == null); // true
179 | print(result?.toString());
180 |
181 | result = _singleItemCollection
182 | .singleOrNullWhere((item) => item != "item"); // ["item"]
183 | assert(result == null); // true
184 | print(result?.toString());
185 |
186 | result =
187 | _numCollection.singleOrNullWhere((item) => item < 3); // [3, 6, 2, 7, 9]
188 | assert(result == 2); // true
189 | print(result?.toString());
190 |
191 | result = _comparableCollection.singleOrNullWhere(
192 | (item) => item.name == "rat",
193 | ); // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
194 | assert(result == Pet("rat", "Mike")); // true
195 | print(result?.toString());
196 |
197 | print('---- ----------------- ----\n');
198 | }
199 |
200 | void _mapList() {
201 | print('---- mapList ----\n');
202 |
203 | final result = _numCollection.mapList((item) => item.toDouble());
204 | assert(result is List);
205 | print(result.toString());
206 |
207 | print('---- ------- ----\n');
208 | }
209 |
210 | void _whereList() {
211 | print('---- whereList ----\n');
212 |
213 | final result = _numCollection.whereList((_) => _ > 4);
214 | assert(result.toString() == [6, 7, 9].toString());
215 | print(result.toString());
216 |
217 | print('---- --------- ----\n');
218 | }
219 |
220 | void _whereMapList() {
221 | print('---- whereMapList ----\n');
222 |
223 | final result = _numCollection.whereMapList((_) => _ > 4, (_) => _.toDouble());
224 | assert(result.toString() == [6, 7, 9].toString());
225 | print(result.toString());
226 |
227 | print('---- ------------ ----\n');
228 | }
229 |
230 | void _mapWhereList() {
231 | print('---- mapWhereList ----\n');
232 |
233 | final result =
234 | _numCollection.mapWhereList((_) => _.toDouble(), (_) => _ > 4);
235 | assert(result.toString() == [6, 7, 9].toString());
236 | print(result.toString());
237 |
238 | print('---- ------------ ----\n');
239 | }
240 |
241 | void _notNull() {
242 | print('---- notNull ----\n');
243 |
244 | final numCollection = [null, ..._numCollection, null];
245 |
246 | final result = numCollection.notNull;
247 | assert(result.toString() == _numCollection.toString());
248 | print(result.toString());
249 |
250 | print('---- ------- ----\n');
251 | }
252 |
253 | void _group() {
254 | print('---- group ----\n');
255 |
256 | final result = _comparableCollection.group((item) => item.name.endsWith('at'));
257 | assert(result.toString() ==
258 | >{
259 | true: [
260 | Pet("rat", "Mike"),
261 | Pet("cat", "Lucy"),
262 | ],
263 | false: [
264 | Pet("dog", "Rex"),
265 | ],
266 | }.toString()); // true
267 | print(result?.toString());
268 |
269 | print('---- ----- ----\n');
270 | }
271 |
272 | void _groupMap() {
273 | print('---- groupMap ----\n');
274 |
275 | final result = _comparableCollection.groupMap(
276 | (item) => item.name.endsWith('at'), (group) => group.length);
277 | assert(result.toString() ==
278 | {
279 | true: 2,
280 | false: 1,
281 | }.toString()); // true
282 | print(result?.toString());
283 |
284 | print('---- -------- ----\n');
285 | }
286 |
287 | void iterableCommonTest() {
288 | _firstOrNull();
289 | _lastOrNull();
290 | _singleOrNull();
291 | _firstOrNullWhere();
292 | _lastOrNullWhere();
293 | _singleOrNullWhere();
294 | _mapList();
295 | _whereList();
296 | _whereMapList();
297 | _mapWhereList();
298 | _notNull();
299 | _group();
300 | _groupMap();
301 | }
302 | ```
303 |
304 | ### Iterable Comparable
305 |
306 | ```dart
307 | final _emptyCollection = [];
308 | final _collection = [
309 | Pet("rat", "Mike"),
310 | Pet("dog", "Rex"),
311 | Pet("cat", "Lucy"),
312 | ];
313 |
314 | void _min() {
315 | print('---- min ----\n');
316 |
317 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
318 | var result = _collection.min;
319 | assert(result == Pet("cat", "Lucy")); // true
320 | print(result?.toString());
321 |
322 | try {
323 | result = _emptyCollection.min; // []
324 | assert(false);
325 | print(result?.toString());
326 | } catch (e) {
327 | assert(e is StateError); // true (No element)
328 | print(e.toString());
329 | }
330 |
331 | print('---- --- ----\n');
332 | }
333 |
334 | void _minWhere() {
335 | print('---- minWhere ----\n');
336 |
337 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
338 | var result = _collection.minWhere((_) => _.name != "cat");
339 | assert(result == Pet("dog", "Rex")); // true
340 | print(result?.toString());
341 |
342 | try {
343 | result = _collection.minWhere((_) => _.name == "rabbit"); // []
344 | assert(false);
345 | print(result?.toString());
346 | } catch (e) {
347 | assert(e is StateError); // true (No element)
348 | print(e.toString());
349 | }
350 |
351 | print('---- --- ----\n');
352 | }
353 |
354 | void _minOrNull() {
355 | print('---- minOrNull ----\n');
356 |
357 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
358 | var result = _collection.minOrNull;
359 | assert(result == Pet("cat", "Lucy")); // true
360 | print(result?.toString());
361 |
362 | result = _emptyCollection.minOrNull; // []
363 | assert(result == null); // true
364 | print(result?.toString());
365 |
366 | print('---- --------- ----\n');
367 | }
368 |
369 | void _minOrNullWhere() {
370 | print('---- minOrNullWhere ----\n');
371 |
372 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
373 | var result = _collection.minOrNullWhere((_) => _.name != "cat");
374 | assert(result == Pet("dog", "Rex")); // true
375 | print(result?.toString());
376 |
377 | result = _emptyCollection.minOrNullWhere((_) => _.name == "rabbit"); // []
378 | assert(result == null); // true
379 | print(result?.toString());
380 |
381 | print('---- --------- ----\n');
382 | }
383 |
384 | void _max() {
385 | print('---- max ----\n');
386 |
387 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
388 | var result = _collection.max;
389 | assert(result == Pet("rat", "Mike")); // true
390 | print(result?.toString());
391 |
392 | try {
393 | result = _emptyCollection.max; // []
394 | assert(false);
395 | print(result?.toString());
396 | } catch (e) {
397 | assert(e is StateError); // true (No element)
398 | print(e.toString());
399 | }
400 |
401 | print('---- --- ----\n');
402 | }
403 |
404 | void _maxWhere() {
405 | print('---- maxWhere ----\n');
406 |
407 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
408 | var result = _collection.maxWhere((_) => _.name != "cat");
409 | assert(result == Pet("rat", "Mike")); // true
410 | print(result?.toString());
411 |
412 | try {
413 | result = _collection.maxWhere((_) => _.name == "rabbit"); // []
414 | assert(false);
415 | print(result?.toString());
416 | } catch (e) {
417 | assert(e is StateError); // true (No element)
418 | print(e.toString());
419 | }
420 |
421 | print('---- --- ----\n');
422 | }
423 |
424 | void _maxOrNull() {
425 | print('---- maxOrNull ----\n');
426 |
427 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
428 | var result = _collection.maxOrNull;
429 | assert(result == Pet("rat", "Mike")); // true
430 | print(result?.toString());
431 |
432 | result = _emptyCollection.maxOrNull; // []
433 | assert(result == null); // true
434 | print(result?.toString());
435 |
436 | print('---- --------- ----\n');
437 | }
438 |
439 | void _maxOrNullWhere() {
440 | print('---- maxOrNullWhere ----\n');
441 |
442 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
443 | var result = _collection.maxOrNullWhere((_) => _.name != "cat");
444 | assert(result == Pet("rat", "Mike")); // true
445 | print(result?.toString());
446 |
447 | result = _emptyCollection.maxOrNullWhere((_) => _.name == "rabbit"); // []
448 | assert(result == null); // true
449 | print(result?.toString());
450 |
451 | print('---- --------- ----\n');
452 | }
453 |
454 | void iterableComparableTest() {
455 | _min();
456 | _minWhere();
457 | _minOrNull();
458 | _minOrNullWhere();
459 | _max();
460 | _maxWhere();
461 | _maxOrNull();
462 | _maxOrNullWhere();
463 | }
464 | ```
465 |
466 | ### Iterable Math
467 |
468 | ```dart
469 | void iterableMathTest() {
470 | print('---- iterable math ----\n');
471 |
472 | final emptyCollection = [];
473 | final oneCollection = [8]; // 8
474 | final manyCollection = [1, 3, 5, 7, 8, 2, 4]; // 30
475 |
476 | assert(emptyCollection.sum == 0); // true
477 | print(emptyCollection.sum);
478 | assert(oneCollection.sum == 8); // true
479 | print(oneCollection.sum);
480 | assert(manyCollection.sum == 30); // true
481 | print(manyCollection.sum);
482 |
483 | assert(emptyCollection.average == 0); // true
484 | print(emptyCollection.average);
485 | assert(oneCollection.average == 8); // true
486 | print(oneCollection.average);
487 | assert(manyCollection.average == 30 / 7); // true
488 | print(manyCollection.average);
489 |
490 | assert(emptyCollection.sumWhere((_) => _ > 4) == 0); // true
491 | print(emptyCollection.sumWhere((_) => _ > 4));
492 | assert(oneCollection.sumWhere((_) => _ > 4) == 8); // true
493 | print(oneCollection.sumWhere((_) => _ > 4));
494 | assert(manyCollection.sumWhere((_) => _ > 4) == 20); // true
495 | print(manyCollection.sumWhere((_) => _ > 4));
496 |
497 | assert(emptyCollection.averageWhere((_) => _ > 4) == 0); // true
498 | print(emptyCollection.averageWhere((_) => _ > 4));
499 | assert(oneCollection.averageWhere((_) => _ > 4) == 8); // true
500 | print(oneCollection.averageWhere((_) => _ > 4));
501 | assert(manyCollection.averageWhere((_) => _ > 4) == 20 / 3); // true
502 | print(manyCollection.averageWhere((_) => _ > 4));
503 |
504 | print('---- ------------- ----\n');
505 | }
506 | ```
507 |
508 | ### Iterable Set
509 |
510 | ```dart
511 | void iterableSetTest() {
512 | print('---- iterable set ----\n');
513 |
514 | final collectionOne = [2, 5, 8, 2];
515 | final collectionTwo = [1, 3, 5, 7];
516 |
517 | print(collectionOne.distinct); // [2, 5, 8]
518 | print(collectionOne.union(collectionTwo)); // [2, 5, 8, 1, 3, 7]
519 | print(collectionOne.intersection(collectionTwo)); // [5]
520 | print(collectionOne.difference(collectionTwo)); // [2, 8]
521 | print(collectionTwo.difference(collectionOne)); // [1, 3, 7]
522 |
523 | print(collectionOne.distinctWhere((_) => _ > 4)); // [2, 5, 8]
524 | print(collectionOne.unionWhere(collectionTwo, (_) => _ > 4)); // [5, 8, 7]
525 | print(collectionOne.intersectionWhere(collectionTwo, (_) => _ < 4)); // []
526 | print(collectionOne.differenceWhere(collectionTwo, (_) => _ < 4)); // [2]
527 | print(collectionTwo.differenceWhere(collectionOne, (_) => _ < 4)); // [1, 3]
528 |
529 | print('---- ------------ ----\n');
530 | }
531 | ```
532 |
533 | ## Getting Started
534 |
535 | For help getting started with Dart, view
536 | [online documentation](https://dart.dev/docs), which offers tutorials,
537 | samples, guidance, and a full API reference.
538 |
--------------------------------------------------------------------------------
/example/bin/main.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'src/iterable.common.examples.dart';
6 | import 'src/iterable.comparable.examples.dart';
7 | import 'src/iterable.math.examples.dart';
8 | import 'src/iterable.set.examples.dart';
9 |
10 | main(List arguments) {
11 | iterableCommonTest();
12 | iterableComparableTest();
13 | iterableMathTest();
14 | iterableSetTest();
15 | }
16 |
--------------------------------------------------------------------------------
/example/bin/src/iterable.common.examples.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'package:flinq/flinq.dart';
6 |
7 | import 'pet.model.dart';
8 |
9 | final _emptyCollection = [];
10 | final _singleItemCollection = ["item"];
11 | final _numCollection = [3, 6, 2, 7, 9];
12 | final _comparableCollection = [
13 | Pet("rat", "Mike"),
14 | Pet("dog", "Rex"),
15 | Pet("cat", "Lucy"),
16 | ];
17 |
18 | void _firstOrNull() {
19 | print('---- firstOrNull ----\n');
20 |
21 | var result = _emptyCollection.firstOrNull; // []
22 | assert(result == null); // true
23 | print(result?.toString());
24 |
25 | result = _singleItemCollection.firstOrNull; // ["item"]
26 | assert(result == "item"); // true
27 | print(result?.toString());
28 |
29 | result = _numCollection.firstOrNull; // [3, 6, 2, 7, 9]
30 | assert(result == 3); // true
31 | print(result?.toString());
32 |
33 | result = _comparableCollection
34 | .firstOrNull; // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
35 | assert(result == Pet("rat", "Mike")); // true
36 | print(result?.toString());
37 |
38 | print('---- ----------- ----\n');
39 | }
40 |
41 | void _lastOrNull() {
42 | print('---- lastOrNull ----\n');
43 |
44 | var result = _emptyCollection.lastOrNull; // []
45 | assert(result == null); // true
46 | print(result?.toString());
47 |
48 | result = _singleItemCollection.lastOrNull; // ["item"]
49 | assert(result == "item"); // true
50 | print(result?.toString());
51 |
52 | result = _numCollection.lastOrNull; // [3, 6, 2, 7, 9]
53 | assert(result == 9); // true
54 | print(result?.toString());
55 |
56 | result = _comparableCollection
57 | .lastOrNull; // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
58 | assert(result == Pet("cat", "Lucy")); // true
59 | print(result?.toString());
60 |
61 | print('---- ---------- ----\n');
62 | }
63 |
64 | void _singleOrNull() {
65 | print('---- singleOrNull ----\n');
66 |
67 | var result = _emptyCollection.singleOrNull; // []
68 | assert(result == null); // true
69 | print(result?.toString());
70 |
71 | result = _singleItemCollection.singleOrNull; // ["item"]
72 | assert(result == "item"); // true
73 | print(result?.toString());
74 |
75 | try {
76 | result = _numCollection.singleOrNull; // [3, 6, 2, 7, 9]
77 | assert(false);
78 | print(result?.toString());
79 | } catch (e) {
80 | assert(e is StateError); // true (Too many elements)
81 | print(e.toString());
82 | }
83 |
84 | try {
85 | result = _comparableCollection
86 | .singleOrNull; // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
87 | assert(false);
88 | print(result?.toString());
89 | } catch (e) {
90 | assert(e is StateError); // true (Too many elements)
91 | print(e.toString());
92 | }
93 |
94 | print('---- ------------ ----\n');
95 | }
96 |
97 | void _firstOrNullWhere() {
98 | print('---- firstOrNullWhere ----\n');
99 |
100 | var result = _emptyCollection.firstOrNullWhere((item) => item != null); // []
101 | assert(result == null); // true
102 | print(result?.toString());
103 |
104 | result = _singleItemCollection
105 | .firstOrNullWhere((item) => item != "item"); // ["item"]
106 | assert(result == null); // true
107 | print(result?.toString());
108 |
109 | result =
110 | _numCollection.firstOrNullWhere((item) => item > 3); // [3, 6, 2, 7, 9]
111 | assert(result == 6); // true
112 | print(result?.toString());
113 |
114 | result = _comparableCollection.firstOrNullWhere(
115 | (item) => item.name.contains("at"),
116 | ); // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
117 | assert(result == Pet("rat", "Mike")); // true
118 | print(result?.toString());
119 |
120 | print('---- ---------------- ----\n');
121 | }
122 |
123 | void _lastOrNullWhere() {
124 | print('---- lastOrNullWhere ----\n');
125 |
126 | var result = _emptyCollection.lastOrNullWhere((item) => item != null); // []
127 | assert(result == null); // true
128 | print(result?.toString());
129 |
130 | result = _singleItemCollection
131 | .lastOrNullWhere((item) => item != "item"); // ["item"]
132 | assert(result == null); // true
133 | print(result?.toString());
134 |
135 | result =
136 | _numCollection.lastOrNullWhere((item) => item > 3); // [3, 6, 2, 7, 9]
137 | assert(result == 9); // true
138 | print(result?.toString());
139 |
140 | result = _comparableCollection.lastOrNullWhere(
141 | (item) => item.name.contains("at"),
142 | ); // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
143 | assert(result == Pet("cat", "Lucy")); // true
144 | print(result?.toString());
145 |
146 | print('---- --------------- ----\n');
147 | }
148 |
149 | void _singleOrNullWhere() {
150 | print('---- singleOrNullWhere ----\n');
151 |
152 | var result = _emptyCollection.singleOrNullWhere((item) => item != null); // []
153 | assert(result == null); // true
154 | print(result?.toString());
155 |
156 | result = _singleItemCollection
157 | .singleOrNullWhere((item) => item != "item"); // ["item"]
158 | assert(result == null); // true
159 | print(result?.toString());
160 |
161 | result =
162 | _numCollection.singleOrNullWhere((item) => item < 3); // [3, 6, 2, 7, 9]
163 | assert(result == 2); // true
164 | print(result?.toString());
165 |
166 | result = _comparableCollection.singleOrNullWhere(
167 | (item) => item.name == "rat",
168 | ); // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
169 | assert(result == Pet("rat", "Mike")); // true
170 | print(result?.toString());
171 |
172 | print('---- ----------------- ----\n');
173 | }
174 |
175 | void _mapList() {
176 | print('---- mapList ----\n');
177 |
178 | final result = _numCollection.mapList((item) => item.toDouble());
179 | assert(result is List);
180 | print(result.toString());
181 |
182 | print('---- ------- ----\n');
183 | }
184 |
185 | void _whereList() {
186 | print('---- whereList ----\n');
187 |
188 | final result = _numCollection.whereList((_) => _ > 4);
189 | assert(result.toString() == [6, 7, 9].toString());
190 | print(result.toString());
191 |
192 | print('---- --------- ----\n');
193 | }
194 |
195 | void _whereMapList() {
196 | print('---- whereMapList ----\n');
197 |
198 | final result = _numCollection.whereMapList((_) => _ > 4, (_) => _.toDouble());
199 | assert(result.toString() == [6, 7, 9].toString());
200 | print(result.toString());
201 |
202 | print('---- ------------ ----\n');
203 | }
204 |
205 | void _mapWhereList() {
206 | print('---- mapWhereList ----\n');
207 |
208 | final result =
209 | _numCollection.mapWhereList((_) => _.toDouble(), (_) => _ > 4);
210 | assert(result.toString() == [6, 7, 9].toString());
211 | print(result.toString());
212 |
213 | print('---- ------------ ----\n');
214 | }
215 |
216 | void _notNull() {
217 | print('---- notNull ----\n');
218 |
219 | final numCollection = [null, ..._numCollection, null];
220 |
221 | final result = numCollection.notNull as Iterable;
222 | assert(result.toString() == _numCollection.toString());
223 | print(result.toString());
224 |
225 | print('---- ------- ----\n');
226 | }
227 |
228 | void _group() {
229 | print('---- group ----\n');
230 |
231 | final result =
232 | _comparableCollection.group((item) => item.name.endsWith('at'));
233 | assert(result.toString() ==
234 | >{
235 | true: [
236 | Pet("rat", "Mike"),
237 | Pet("cat", "Lucy"),
238 | ],
239 | false: [
240 | Pet("dog", "Rex"),
241 | ],
242 | }.toString()); // true
243 | print(result.toString());
244 |
245 | print('---- ----- ----\n');
246 | }
247 |
248 | void _groupMap() {
249 | print('---- groupMap ----\n');
250 |
251 | final result = _comparableCollection.groupMap(
252 | (item) => item.name.endsWith('at'), (group) => group.length);
253 | assert(result.toString() ==
254 | {
255 | true: 2,
256 | false: 1,
257 | }.toString()); // true
258 | print(result.toString());
259 |
260 | print('---- -------- ----\n');
261 | }
262 |
263 | void iterableCommonTest() {
264 | _firstOrNull();
265 | _lastOrNull();
266 | _singleOrNull();
267 | _firstOrNullWhere();
268 | _lastOrNullWhere();
269 | _singleOrNullWhere();
270 | _mapList();
271 | _whereList();
272 | _whereMapList();
273 | _mapWhereList();
274 | _notNull();
275 | _group();
276 | _groupMap();
277 | }
278 |
--------------------------------------------------------------------------------
/example/bin/src/iterable.comparable.examples.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'package:flinq/flinq.dart';
6 |
7 | import 'pet.model.dart';
8 |
9 | final _emptyCollection = [];
10 | final _collection = [
11 | Pet("rat", "Mike"),
12 | Pet("dog", "Rex"),
13 | Pet("cat", "Lucy"),
14 | ];
15 |
16 | void _min() {
17 | print('---- min ----\n');
18 |
19 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
20 | var result = _collection.min;
21 | assert(result == Pet("cat", "Lucy")); // true
22 | print(result.toString());
23 |
24 | try {
25 | result = _emptyCollection.min; // []
26 | assert(false);
27 | print(result.toString());
28 | } catch (e) {
29 | assert(e is StateError); // true (No element)
30 | print(e.toString());
31 | }
32 |
33 | print('---- --- ----\n');
34 | }
35 |
36 | void _minWhere() {
37 | print('---- minWhere ----\n');
38 |
39 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
40 | var result = _collection.minWhere((_) => _.name != "cat");
41 | assert(result == Pet("dog", "Rex")); // true
42 | print(result.toString());
43 |
44 | try {
45 | result = _collection.minWhere((_) => _.name == "rabbit"); // []
46 | assert(false);
47 | print(result.toString());
48 | } catch (e) {
49 | assert(e is StateError); // true (No element)
50 | print(e.toString());
51 | }
52 |
53 | print('---- --- ----\n');
54 | }
55 |
56 | void _minOrNull() {
57 | print('---- minOrNull ----\n');
58 |
59 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
60 | var result = _collection.minOrNull;
61 | assert(result == Pet("cat", "Lucy")); // true
62 | print(result?.toString());
63 |
64 | result = _emptyCollection.minOrNull; // []
65 | assert(result == null); // true
66 | print(result?.toString());
67 |
68 | print('---- --------- ----\n');
69 | }
70 |
71 | void _minOrNullWhere() {
72 | print('---- minOrNullWhere ----\n');
73 |
74 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
75 | var result = _collection.minOrNullWhere((_) => _.name != "cat");
76 | assert(result == Pet("dog", "Rex")); // true
77 | print(result?.toString());
78 |
79 | result = _emptyCollection.minOrNullWhere((_) => _.name == "rabbit"); // []
80 | assert(result == null); // true
81 | print(result?.toString());
82 |
83 | print('---- --------- ----\n');
84 | }
85 |
86 | void _max() {
87 | print('---- max ----\n');
88 |
89 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
90 | var result = _collection.max;
91 | assert(result == Pet("rat", "Mike")); // true
92 | print(result.toString());
93 |
94 | try {
95 | result = _emptyCollection.max; // []
96 | assert(false);
97 | print(result.toString());
98 | } catch (e) {
99 | assert(e is StateError); // true (No element)
100 | print(e.toString());
101 | }
102 |
103 | print('---- --- ----\n');
104 | }
105 |
106 | void _maxWhere() {
107 | print('---- maxWhere ----\n');
108 |
109 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
110 | var result = _collection.maxWhere((_) => _.name != "cat");
111 | assert(result == Pet("rat", "Mike")); // true
112 | print(result.toString());
113 |
114 | try {
115 | result = _collection.maxWhere((_) => _.name == "rabbit"); // []
116 | assert(false);
117 | print(result.toString());
118 | } catch (e) {
119 | assert(e is StateError); // true (No element)
120 | print(e.toString());
121 | }
122 |
123 | print('---- --- ----\n');
124 | }
125 |
126 | void _maxOrNull() {
127 | print('---- maxOrNull ----\n');
128 |
129 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
130 | var result = _collection.maxOrNull;
131 | assert(result == Pet("rat", "Mike")); // true
132 | print(result?.toString());
133 |
134 | result = _emptyCollection.maxOrNull; // []
135 | assert(result == null); // true
136 | print(result?.toString());
137 |
138 | print('---- --------- ----\n');
139 | }
140 |
141 | void _maxOrNullWhere() {
142 | print('---- maxOrNullWhere ----\n');
143 |
144 | // [ Pet("rat", "Mike"), Pet("dog", "Rex"), Pet("cat", "Lucy") ]
145 | var result = _collection.maxOrNullWhere((_) => _.name != "cat");
146 | assert(result == Pet("rat", "Mike")); // true
147 | print(result?.toString());
148 |
149 | result = _emptyCollection.maxOrNullWhere((_) => _.name == "rabbit"); // []
150 | assert(result == null); // true
151 | print(result?.toString());
152 |
153 | print('---- --------- ----\n');
154 | }
155 |
156 | void iterableComparableTest() {
157 | _min();
158 | _minWhere();
159 | _minOrNull();
160 | _minOrNullWhere();
161 | _max();
162 | _maxWhere();
163 | _maxOrNull();
164 | _maxOrNullWhere();
165 | }
166 |
--------------------------------------------------------------------------------
/example/bin/src/iterable.math.examples.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'package:flinq/flinq.dart';
6 |
7 | void iterableMathTest() {
8 | print('---- iterable math ----\n');
9 |
10 | final emptyCollection = [];
11 | final oneCollection = [8]; // 8
12 | final manyCollection = [1, 3, 5, 7, 8, 2, 4]; // 30
13 |
14 | assert(emptyCollection.sum == 0); // true
15 | print(emptyCollection.sum);
16 | assert(oneCollection.sum == 8); // true
17 | print(oneCollection.sum);
18 | assert(manyCollection.sum == 30); // true
19 | print(manyCollection.sum);
20 |
21 | assert(emptyCollection.average == 0); // true
22 | print(emptyCollection.average);
23 | assert(oneCollection.average == 8); // true
24 | print(oneCollection.average);
25 | assert(manyCollection.average == 30 / 7); // true
26 | print(manyCollection.average);
27 |
28 | assert(emptyCollection.sumWhere((_) => _ > 4) == 0); // true
29 | print(emptyCollection.sumWhere((_) => _ > 4));
30 | assert(oneCollection.sumWhere((_) => _ > 4) == 8); // true
31 | print(oneCollection.sumWhere((_) => _ > 4));
32 | assert(manyCollection.sumWhere((_) => _ > 4) == 20); // true
33 | print(manyCollection.sumWhere((_) => _ > 4));
34 |
35 | assert(emptyCollection.averageWhere((_) => _ > 4) == 0); // true
36 | print(emptyCollection.averageWhere((_) => _ > 4));
37 | assert(oneCollection.averageWhere((_) => _ > 4) == 8); // true
38 | print(oneCollection.averageWhere((_) => _ > 4));
39 | assert(manyCollection.averageWhere((_) => _ > 4) == 20 / 3); // true
40 | print(manyCollection.averageWhere((_) => _ > 4));
41 |
42 | print('---- ------------- ----\n');
43 | }
44 |
--------------------------------------------------------------------------------
/example/bin/src/iterable.set.examples.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'package:flinq/flinq.dart';
6 |
7 | void iterableSetTest() {
8 | print('---- iterable set ----\n');
9 |
10 | final collectionOne = [2, 5, 8, 2];
11 | final collectionTwo = [1, 3, 5, 7];
12 |
13 | print(collectionOne.distinct); // [2, 5, 8]
14 | print(collectionOne.union(collectionTwo)); // [2, 5, 8, 1, 3, 7]
15 | print(collectionOne.intersection(collectionTwo)); // [5]
16 | print(collectionOne.difference(collectionTwo)); // [2, 8]
17 | print(collectionTwo.difference(collectionOne)); // [1, 3, 7]
18 |
19 | print(collectionOne.distinctWhere((_) => _ > 4)); // [2, 5, 8]
20 | print(collectionOne.unionWhere(collectionTwo, (_) => _ > 4)); // [5, 8, 7]
21 | print(collectionOne.intersectionWhere(collectionTwo, (_) => _ < 4)); // []
22 | print(collectionOne.differenceWhere(collectionTwo, (_) => _ < 4)); // [2]
23 | print(collectionTwo.differenceWhere(collectionOne, (_) => _ < 4)); // [1, 3]
24 |
25 | print('---- ------------ ----\n');
26 | }
27 |
--------------------------------------------------------------------------------
/example/bin/src/pet.model.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | class Pet implements Comparable {
6 | const Pet(this.name, this.nickname);
7 |
8 | final String name;
9 | final String nickname;
10 |
11 | @override
12 | int compareTo(Pet other) => name.compareTo(other.name);
13 |
14 | @override
15 | bool operator ==(Object other) =>
16 | other is Pet ? other.name == name && other.nickname == nickname : false;
17 |
18 | @override
19 | int get hashCode => name.hashCode + nickname.hashCode;
20 |
21 | @override
22 | String toString() => '$name ($nickname)';
23 | }
24 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flinq_example
2 | description: Example command line application of flinq package.
3 |
4 | environment:
5 | sdk: '>=2.12.0 <3.0.0'
6 |
7 | dependencies:
8 | flinq:
9 | path: ../
10 |
--------------------------------------------------------------------------------
/lib/flinq.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | library flinq;
6 |
7 | export 'src/iterable.common.extension.dart';
8 | export 'src/iterable.comparable.extension.dart';
9 | export 'src/iterable.math.extension.dart';
10 | export 'src/iterable.set.extension.dart';
11 |
--------------------------------------------------------------------------------
/lib/src/iterable.common.extension.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'package:collection/collection.dart' show IterableExtension;
6 |
7 | /// Common extensions for `Iterable`
8 | extension IterableCommonExtension on Iterable {
9 | /// Returns the first element.
10 | ///
11 | /// If `this` is empty, the result of invoking is [null].
12 | /// Otherwise returns the first element in the iteration order,
13 | /// equivalent to `this.elementAt(0)`.
14 | T? get firstOrNull => this.firstWhereOrNull((_) => true);
15 |
16 | /// Returns the last element.
17 | ///
18 | /// If `this` is empty, the result of invoking is [null].
19 | /// Otherwise may iterate through the elements and returns the last one
20 | /// seen.
21 | /// Some iterables may have more efficient ways to find the last element
22 | /// (for example a list can directly access the last element,
23 | /// without iterating through the previous ones).
24 | T? get lastOrNull => this.lastWhereOrNull((_) => true);
25 |
26 | /// Checks that this iterable has only one element, and returns that element.
27 | ///
28 | /// Returns [null] if there are either no elements or more than one element.
29 | T? get singleOrNull => this.singleWhereOrNull((_) => true);
30 |
31 | /// Returns the first element that satisfies the given predicate [test].
32 | ///
33 | /// Iterates through elements and returns the first to satisfy [test].
34 | ///
35 | /// If no element satisfies [test], the result of invoking is [null].
36 | T? firstOrNullWhere(bool test(T element)) => this.firstWhereOrNull(test);
37 |
38 | /// Returns the last element that satisfies the given predicate [test].
39 | ///
40 | /// An iterable that can access its elements directly may check its
41 | /// elements in any order (for example a list starts by checking the
42 | /// last element and then moves towards the start of the list).
43 | /// The default implementation iterates elements in iteration order,
44 | /// checks `test(element)` for each,
45 | /// and finally returns that last one that matched.
46 | ///
47 | /// If no element satisfies [test], the result of invoking is [null].
48 | T? lastOrNullWhere(bool test(T element)) => this.lastWhereOrNull(test);
49 |
50 | /// Returns the single element that satisfies [test].
51 | ///
52 | /// Returns [null] if there are either no elements or more than one element
53 | /// satisfying [test].
54 | T? singleOrNullWhere(bool test(T element)) => this.singleWhereOrNull(test);
55 |
56 | /// Maps [Iterable] and casts it to a [List].
57 | ///
58 | /// Returns a new lazy [List] with elements that are created by
59 | /// calling `f` on each element of this `List` in iteration order.
60 | ///
61 | /// This method returns a view of the mapped elements. As long as the
62 | /// returned [List] is not iterated over, the supplied function [f] will
63 | /// not be invoked. The transformed elements will not be cached. Iterating
64 | /// multiple times over the returned [List] will invoke the supplied
65 | /// function [f] multiple times on the same element.
66 | ///
67 | /// Methods on the returned iterable are allowed to omit calling `f`
68 | /// on any element where the result isn't needed.
69 | /// For example, [elementAt] may call `f` only once.
70 | List mapList(E f(T e)) => this.map(f).toList();
71 |
72 | /// Filters [Iterable] and casts it to a [List].
73 | ///
74 | /// Returns a new lazy [List] with all elements that satisfy the
75 | /// predicate [test].
76 | ///
77 | /// The matching elements have the same order in the returned iterable
78 | /// as they have in [iterator].
79 | ///
80 | /// This method returns a view of the mapped elements.
81 | /// As long as the returned [List] is not iterated over,
82 | /// the supplied function [test] will not be invoked.
83 | /// Iterating will not cache results, and thus iterating multiple times over
84 | /// the returned [List] may invoke the supplied
85 | List whereList(bool test(T element)) => this.where(test).toList();
86 |
87 | /// Filters [Iterable], then mapps [Iterable] and then casts it to a [List].
88 | ///
89 | /// For more info about filtering refer to [Iterable.where].
90 | /// For more info about mapping refer to [Iterable.map].
91 | List whereMapList(bool test(T element), E f(T e)) =>
92 | this.where(test).mapList(f);
93 |
94 | /// Maps [Iterable], then filters [Iterable] and then casts it to a [List].
95 | ///
96 | /// For more info about mapping refer to [Iterable.map].
97 | /// For more info about filtering refer to [Iterable.where].
98 | List mapWhereList(E f(T e), bool test(E element)) =>
99 | this.map(f).whereList(test);
100 |
101 | /// Returns `this` iterable without any `null` values within this [Iterable].
102 | ///
103 | /// Not null items of [Iterable] is achieved by [Iterable.where].
104 | /// Predicate of [Iterable.where] is `(item) => item != null`.
105 | ///
106 | /// For more info about filtering refer to [Iterable.where].
107 | Iterable get notNull => this.where((_) => _ != null).toList();
108 |
109 | /// Groups [Iterable] via `K by(T item)`
110 | ///
111 | /// if [this] is empty, the result of invoking is [>{}]
112 | Map> group(K by(T item)) {
113 | final map = >{};
114 |
115 | this.forEach((value) {
116 | final key = by(value);
117 |
118 | if (map.containsKey(key)) {
119 | map[key]!.add(value);
120 | } else {
121 | map[key] = [value];
122 | }
123 | });
124 |
125 | return map;
126 | }
127 |
128 | /// Groups [Iterable] via `K by(T item)` and maps it using `V as(List item)` conversion.
129 | ///
130 | /// For more info about mapping refer to [Iterable.map].
131 | Map groupMap(K by(T item), V as(List item)) =>
132 | group(by).map((k, v) => MapEntry(k, as(v)));
133 | }
134 |
--------------------------------------------------------------------------------
/lib/src/iterable.comparable.extension.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | /// Extensions for comparable `Iterable`
6 | extension IterableComparableExtension on Iterable {
7 | Iterable get _sorted => this.toList()..sort();
8 |
9 | /// Returns the element with minimum value.
10 | ///
11 | /// If `this` is empty, [StateError] will be thrown.
12 | T get min {
13 | if (this.isEmpty) {
14 | throw StateError('No element');
15 | }
16 | return _sorted.first;
17 | }
18 |
19 | /// Returns the element with maximum value.
20 | ///
21 | /// If `this` is empty, [StateError] will be thrown.
22 | T get max {
23 | if (this.isEmpty) {
24 | throw StateError('No element');
25 | }
26 | return _sorted.last;
27 | }
28 |
29 | /// Returns the element with minimum value.
30 | ///
31 | /// If `this` is empty, the result of invoking is [null].
32 | T? get minOrNull {
33 | if (this.isEmpty) {
34 | return null;
35 | }
36 | return _sorted.first;
37 | }
38 |
39 | /// Returns the element with maximum value.
40 | ///
41 | /// If `this` is empty, the result of invoking is [null].
42 | T? get maxOrNull {
43 | if (this.isEmpty) {
44 | return null;
45 | }
46 | return _sorted.last;
47 | }
48 |
49 | /// Returns the element with minimum value of filtered
50 | /// collection by `test` predicate.
51 | ///
52 | /// If `this` is empty, [StateError] will be thrown.
53 | ///
54 | /// For more info about filtering refer to [Iterable.where].
55 | T minWhere(bool test(T element)) => this.where(test).min;
56 |
57 | /// Returns the element with maximum value of filtered
58 | /// collection by `test` predicate.
59 | ///
60 | /// If `this` is empty, [StateError] will be thrown.
61 | ///
62 | /// For more info about filtering refer to [Iterable.where].
63 | T maxWhere(bool test(T element)) => this.where(test).max;
64 |
65 | /// Returns the element with minimum value of filtered
66 | /// collection by `test` predicate.
67 | ///
68 | /// If `this` is empty, the result of invoking is [null].
69 | ///
70 | /// For more info about filtering refer to [Iterable.where].
71 | T? minOrNullWhere(bool test(T element)) => this.where(test).minOrNull;
72 |
73 | /// Returns the element with maximum value of filtered
74 | /// collection by `test` predicate.
75 | ///
76 | /// If `this` is empty, the result of invoking is [null].
77 | ///
78 | /// For more info about filtering refer to [Iterable.where].
79 | T? maxOrNullWhere(bool test(T element)) => this.where(test).maxOrNull;
80 | }
81 |
--------------------------------------------------------------------------------
/lib/src/iterable.math.extension.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | /// Math extensions for numeric `Iterable`
6 | extension IterableMathExtension on Iterable {
7 | /// Returns the sum of all elements.
8 | ///
9 | /// If `this` is empty, the result of invoking is [0].
10 | num get sum => this.fold(0, (prev, element) => prev + element);
11 |
12 | /// Returns the average of all elements.
13 | ///
14 | /// If `this` is empty, the result of invoking is [0].
15 | num get average => this.isNotEmpty ? sum / this.length : 0;
16 |
17 | /// Returns the sum of all elements filtered by `test` predicate.
18 | ///
19 | /// If `this` is empty, the result of invoking is [0].
20 | ///
21 | /// For more info about filtering refer to [Iterable.where].
22 | num sumWhere(bool test(T element)) => this.where(test).sum;
23 |
24 | /// Returns the average of all elements filtered by `test` predicate.
25 | ///
26 | /// If `this` is empty, the result of invoking is [0].
27 | ///
28 | /// For more info about filtering refer to [Iterable.where].
29 | num averageWhere(bool test(T element)) => this.where(test).average;
30 | }
31 |
--------------------------------------------------------------------------------
/lib/src/iterable.set.extension.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | /// Set extensions for `Iterable`
6 | extension IterableSetExtension on Iterable {
7 | /// Returns new list of objects in which each object can
8 | /// occur only once
9 | ///
10 | /// The order of the elements is not guaranteed to be the same
11 | /// as for the iterable.
12 | List get distinct => this.toSet().toList();
13 |
14 | /// Returns new list of objects filtered by `test` predicate
15 | /// in which each object can occur only once
16 | ///
17 | /// The order of the elements is not guaranteed to be the same
18 | /// as for the iterable.
19 | ///
20 | /// For more info about filtering refer to [Iterable.where].
21 | List distinctWhere(bool test(T element)) =>
22 | this.where(test).toSet().toList();
23 |
24 | /// Returns a new list which is the intersection between this list and [other].
25 | ///
26 | /// That is, the returned list contains all the elements of this [List] that
27 | /// are also elements of [other] according to `other.contains`.
28 | ///
29 | /// Note that `this` list and `other` will be cleared from item duplicates.
30 | List intersection(List other) =>
31 | this.toSet().intersection(other.toSet()).toList();
32 |
33 | /// Returns a new list which is the intersection between filtered this list
34 | /// by `test` predicate and [other].
35 | ///
36 | /// That is, the returned list contains all the elements of this [List] that
37 | /// are also elements of [other] according to `other.contains`.
38 | ///
39 | /// Note that filtering is applied to both `this` and `other` [Iterable]s.
40 | ///
41 | /// Note that `this` list and `other` will be cleared from item duplicates.
42 | List intersectionWhere(List other, bool test(T element)) =>
43 | this.where(test).toSet().intersection(other.where(test).toSet()).toList();
44 |
45 | /// Returns a new list which contains all the elements of this list and [other].
46 | ///
47 | /// That is, the returned list contains all the elements of this [list] and
48 | /// all the elements of [other].
49 | ///
50 | /// Note that `this` list and `other` will be cleared from item duplicates.
51 | List union(List other) => this.toSet().union(other.toSet()).toList();
52 |
53 | /// Returns a new list which contains all the elements of filtered this list
54 | /// by `test` and [other].
55 | ///
56 | /// That is, the returned list contains all the elements of this [list] and
57 | /// all the elements of [other].
58 | ///
59 | /// Note that filtering is applied to both `this` and `other` [Iterable]s.
60 | ///
61 | /// Note that `this` list and `other` will be cleared from item duplicates.
62 | List unionWhere(List other, bool test(T element)) =>
63 | this.where(test).toSet().union(other.where(test).toSet()).toList();
64 |
65 | /// Returns a new list with the elements of this that are not in [other].
66 | ///
67 | /// That is, the returned list contains all the elements of this [Set] that
68 | /// are not elements of [other] according to `other.contains`.
69 | ///
70 | /// Note that `this` list and `other` will be cleared from item duplicates.
71 | List difference(List other) =>
72 | this.toSet().difference(other.toSet()).toList();
73 |
74 | /// Returns a new list with the elements of filtered this by `test` that
75 | /// are not in [other].
76 | ///
77 | /// That is, the returned list contains all the elements of this [Set] that
78 | /// are not elements of [other] according to `other.contains`.
79 | ///
80 | /// Note that filtering is applied to both `this` and `other` [Iterable]s.
81 | ///
82 | /// Note that `this` list and `other` will be cleared from item duplicates.
83 | List differenceWhere(List other, bool test(T element)) =>
84 | this.where(test).toSet().difference(other.where(test).toSet()).toList();
85 | }
86 |
--------------------------------------------------------------------------------
/publish_commands.txt:
--------------------------------------------------------------------------------
1 | flutter packages pub publish --dry-run
2 | flutter packages pub publish
3 |
4 | pub uploader --package= add
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | _fe_analyzer_shared:
5 | dependency: transitive
6 | description:
7 | name: _fe_analyzer_shared
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "18.0.0"
11 | analyzer:
12 | dependency: transitive
13 | description:
14 | name: analyzer
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "1.2.0"
18 | args:
19 | dependency: transitive
20 | description:
21 | name: args
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "2.0.0"
25 | async:
26 | dependency: transitive
27 | description:
28 | name: async
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "2.5.0"
32 | boolean_selector:
33 | dependency: transitive
34 | description:
35 | name: boolean_selector
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "2.1.0"
39 | charcode:
40 | dependency: transitive
41 | description:
42 | name: charcode
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.2.0"
46 | cli_util:
47 | dependency: transitive
48 | description:
49 | name: cli_util
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "0.3.0"
53 | collection:
54 | dependency: "direct main"
55 | description:
56 | name: collection
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "1.15.0"
60 | convert:
61 | dependency: transitive
62 | description:
63 | name: convert
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "3.0.0"
67 | coverage:
68 | dependency: transitive
69 | description:
70 | name: coverage
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "1.0.2"
74 | crypto:
75 | dependency: transitive
76 | description:
77 | name: crypto
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "3.0.0"
81 | file:
82 | dependency: transitive
83 | description:
84 | name: file
85 | url: "https://pub.dartlang.org"
86 | source: hosted
87 | version: "6.1.0"
88 | glob:
89 | dependency: transitive
90 | description:
91 | name: glob
92 | url: "https://pub.dartlang.org"
93 | source: hosted
94 | version: "2.0.0"
95 | http_multi_server:
96 | dependency: transitive
97 | description:
98 | name: http_multi_server
99 | url: "https://pub.dartlang.org"
100 | source: hosted
101 | version: "3.0.0"
102 | http_parser:
103 | dependency: transitive
104 | description:
105 | name: http_parser
106 | url: "https://pub.dartlang.org"
107 | source: hosted
108 | version: "4.0.0"
109 | io:
110 | dependency: transitive
111 | description:
112 | name: io
113 | url: "https://pub.dartlang.org"
114 | source: hosted
115 | version: "1.0.0"
116 | js:
117 | dependency: transitive
118 | description:
119 | name: js
120 | url: "https://pub.dartlang.org"
121 | source: hosted
122 | version: "0.6.3"
123 | logging:
124 | dependency: transitive
125 | description:
126 | name: logging
127 | url: "https://pub.dartlang.org"
128 | source: hosted
129 | version: "1.0.0"
130 | matcher:
131 | dependency: transitive
132 | description:
133 | name: matcher
134 | url: "https://pub.dartlang.org"
135 | source: hosted
136 | version: "0.12.10"
137 | meta:
138 | dependency: transitive
139 | description:
140 | name: meta
141 | url: "https://pub.dartlang.org"
142 | source: hosted
143 | version: "1.3.0"
144 | mime:
145 | dependency: transitive
146 | description:
147 | name: mime
148 | url: "https://pub.dartlang.org"
149 | source: hosted
150 | version: "1.0.0"
151 | node_preamble:
152 | dependency: transitive
153 | description:
154 | name: node_preamble
155 | url: "https://pub.dartlang.org"
156 | source: hosted
157 | version: "2.0.0"
158 | package_config:
159 | dependency: transitive
160 | description:
161 | name: package_config
162 | url: "https://pub.dartlang.org"
163 | source: hosted
164 | version: "2.0.0"
165 | path:
166 | dependency: transitive
167 | description:
168 | name: path
169 | url: "https://pub.dartlang.org"
170 | source: hosted
171 | version: "1.8.0"
172 | pedantic:
173 | dependency: "direct dev"
174 | description:
175 | name: pedantic
176 | url: "https://pub.dartlang.org"
177 | source: hosted
178 | version: "1.11.0"
179 | pool:
180 | dependency: transitive
181 | description:
182 | name: pool
183 | url: "https://pub.dartlang.org"
184 | source: hosted
185 | version: "1.5.0"
186 | pub_semver:
187 | dependency: transitive
188 | description:
189 | name: pub_semver
190 | url: "https://pub.dartlang.org"
191 | source: hosted
192 | version: "2.0.0"
193 | shelf:
194 | dependency: transitive
195 | description:
196 | name: shelf
197 | url: "https://pub.dartlang.org"
198 | source: hosted
199 | version: "1.1.0"
200 | shelf_packages_handler:
201 | dependency: transitive
202 | description:
203 | name: shelf_packages_handler
204 | url: "https://pub.dartlang.org"
205 | source: hosted
206 | version: "3.0.0"
207 | shelf_static:
208 | dependency: transitive
209 | description:
210 | name: shelf_static
211 | url: "https://pub.dartlang.org"
212 | source: hosted
213 | version: "1.0.0"
214 | shelf_web_socket:
215 | dependency: transitive
216 | description:
217 | name: shelf_web_socket
218 | url: "https://pub.dartlang.org"
219 | source: hosted
220 | version: "1.0.1"
221 | source_map_stack_trace:
222 | dependency: transitive
223 | description:
224 | name: source_map_stack_trace
225 | url: "https://pub.dartlang.org"
226 | source: hosted
227 | version: "2.1.0"
228 | source_maps:
229 | dependency: transitive
230 | description:
231 | name: source_maps
232 | url: "https://pub.dartlang.org"
233 | source: hosted
234 | version: "0.10.10"
235 | source_span:
236 | dependency: transitive
237 | description:
238 | name: source_span
239 | url: "https://pub.dartlang.org"
240 | source: hosted
241 | version: "1.8.1"
242 | stack_trace:
243 | dependency: transitive
244 | description:
245 | name: stack_trace
246 | url: "https://pub.dartlang.org"
247 | source: hosted
248 | version: "1.10.0"
249 | stream_channel:
250 | dependency: transitive
251 | description:
252 | name: stream_channel
253 | url: "https://pub.dartlang.org"
254 | source: hosted
255 | version: "2.1.0"
256 | string_scanner:
257 | dependency: transitive
258 | description:
259 | name: string_scanner
260 | url: "https://pub.dartlang.org"
261 | source: hosted
262 | version: "1.1.0"
263 | term_glyph:
264 | dependency: transitive
265 | description:
266 | name: term_glyph
267 | url: "https://pub.dartlang.org"
268 | source: hosted
269 | version: "1.2.0"
270 | test:
271 | dependency: "direct dev"
272 | description:
273 | name: test
274 | url: "https://pub.dartlang.org"
275 | source: hosted
276 | version: "1.16.8"
277 | test_api:
278 | dependency: transitive
279 | description:
280 | name: test_api
281 | url: "https://pub.dartlang.org"
282 | source: hosted
283 | version: "0.3.0"
284 | test_core:
285 | dependency: transitive
286 | description:
287 | name: test_core
288 | url: "https://pub.dartlang.org"
289 | source: hosted
290 | version: "0.3.19"
291 | typed_data:
292 | dependency: transitive
293 | description:
294 | name: typed_data
295 | url: "https://pub.dartlang.org"
296 | source: hosted
297 | version: "1.3.0"
298 | vm_service:
299 | dependency: transitive
300 | description:
301 | name: vm_service
302 | url: "https://pub.dartlang.org"
303 | source: hosted
304 | version: "6.1.0+1"
305 | watcher:
306 | dependency: transitive
307 | description:
308 | name: watcher
309 | url: "https://pub.dartlang.org"
310 | source: hosted
311 | version: "1.0.0"
312 | web_socket_channel:
313 | dependency: transitive
314 | description:
315 | name: web_socket_channel
316 | url: "https://pub.dartlang.org"
317 | source: hosted
318 | version: "2.0.0"
319 | webkit_inspection_protocol:
320 | dependency: transitive
321 | description:
322 | name: webkit_inspection_protocol
323 | url: "https://pub.dartlang.org"
324 | source: hosted
325 | version: "1.0.0"
326 | yaml:
327 | dependency: transitive
328 | description:
329 | name: yaml
330 | url: "https://pub.dartlang.org"
331 | source: hosted
332 | version: "3.1.0"
333 | sdks:
334 | dart: ">=2.12.0 <3.0.0"
335 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flinq
2 | version: 2.0.2
3 | homepage: https://github.com/marchdev-tk/flinq
4 | issue_tracker: https://github.com/marchdev-tk/flinq/issues
5 | description: Extended capabilities for collections. It's a bunch of shortcuts to avoid unnecesary boilerplate work with collections.
6 |
7 | environment:
8 | sdk: '>=2.12.0 <3.0.0'
9 |
10 | dependencies:
11 | collection: ^1.15.0
12 |
13 | dev_dependencies:
14 | pedantic: ^1.11.0
15 | test: ^1.16.5
16 |
--------------------------------------------------------------------------------
/test/flinq_test.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | import 'package:test/test.dart';
6 | import 'package:flinq/flinq.dart';
7 |
8 | part 'src/iterable.comparable.test.dart';
9 | part 'src/iterable.common.test.dart';
10 | part 'src/iterable.math.test.dart';
11 | part 'src/iterable.set.test.dart';
12 |
13 | final Iterable _emptyCollection = [];
14 | final Iterable _oneItemCollection = [7];
15 | final Iterable _manyCollection = [4, 3, 6, 1, 9, 5];
16 | /// to run tests use `pub run test`
17 | void main() {
18 | iterableCommonTests();
19 | iterableComparableTests();
20 | iterableMathTests();
21 | iterableSetTests();
22 | }
23 |
--------------------------------------------------------------------------------
/test/src/iterable.common.test.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | part of '../flinq_test.dart';
6 |
7 | void iterableCommonTests() {
8 | firstOrNullTests();
9 | lastOrNullTests();
10 | singleOrNullTests();
11 | firstOrNullWhereTests();
12 | lastOrNullWhereTests();
13 | singleOrNullWhereTests();
14 | mapListTests();
15 | mapWhereListTests();
16 | whereMapListTests();
17 | notNullTests();
18 | groupTests();
19 | groupMapTest();
20 | }
21 |
22 | void firstOrNullTests() {
23 | test(
24 | 'Iterable.firstOrNull on empty collection',
25 | () => expect(_emptyCollection.firstOrNull, null),
26 | );
27 | test(
28 | 'Iterable.firstOrNull on collection with 1 element',
29 | () => expect(_oneItemCollection.firstOrNull, 7),
30 | );
31 | test(
32 | 'Iterable.firstOrNull on collection with many elements',
33 | () => expect(_manyCollection.firstOrNull, 4),
34 | );
35 | }
36 |
37 | void lastOrNullTests() {
38 | test(
39 | 'Iterable.lastOrNull on empty collection',
40 | () => expect(_emptyCollection.lastOrNull, null),
41 | );
42 | test(
43 | 'Iterable.lastOrNull on collection with 1 element',
44 | () => expect(_oneItemCollection.lastOrNull, 7),
45 | );
46 | test(
47 | 'Iterable.lastOrNull on collection with many elements',
48 | () => expect(_manyCollection.lastOrNull, 5),
49 | );
50 | }
51 |
52 | void singleOrNullTests() {
53 | test(
54 | 'Iterable.singleOrNull on empty collection',
55 | () => expect(_emptyCollection.singleOrNull, null),
56 | );
57 | test(
58 | 'Iterable.singleOrNull on collection with 1 element',
59 | () => expect(_oneItemCollection.singleOrNull, 7),
60 | );
61 | test(
62 | 'Iterable.singleOrNull on collection with many elements',
63 | () => expect(_manyCollection.singleOrNull, null),
64 | );
65 | }
66 |
67 | void firstOrNullWhereTests() {
68 | test(
69 | 'Iterable.firstOrNullWhere on empty collection',
70 | () => expect(_emptyCollection.firstOrNullWhere((_) => true), null),
71 | );
72 | test(
73 | 'Iterable.firstOrNullWhere on collection with 1 element, found',
74 | () => expect(_oneItemCollection.firstOrNullWhere((_) => _ > 4), 7),
75 | );
76 | test(
77 | 'Iterable.firstOrNullWhere on collection with 1 element, not found',
78 | () => expect(_oneItemCollection.firstOrNullWhere((_) => _ < 4), null),
79 | );
80 | test(
81 | 'Iterable.firstOrNullWhere on collection with many elements, found',
82 | () => expect(_manyCollection.firstOrNullWhere((_) => _ > 4), 6),
83 | );
84 | test(
85 | 'Iterable.firstOrNullWhere on collection with many elements, not found',
86 | () => expect(_manyCollection.firstOrNullWhere((_) => _ > 10), null),
87 | );
88 | }
89 |
90 | void lastOrNullWhereTests() {
91 | test(
92 | 'Iterable.lastOrNullWhere on empty collection',
93 | () => expect(_emptyCollection.lastOrNullWhere((_) => true), null),
94 | );
95 | test(
96 | 'Iterable.lastOrNullWhere on collection with 1 element, found',
97 | () => expect(_oneItemCollection.lastOrNullWhere((_) => _ > 4), 7),
98 | );
99 | test(
100 | 'Iterable.lastOrNullWhere on collection with 1 element, not found',
101 | () => expect(_oneItemCollection.lastOrNullWhere((_) => _ < 4), null),
102 | );
103 | test(
104 | 'Iterable.lastOrNullWhere on collection with many elements, found',
105 | () => expect(_manyCollection.lastOrNullWhere((_) => _ > 5), 9),
106 | );
107 | test(
108 | 'Iterable.lastOrNullWhere on collection with many elements, not found',
109 | () => expect(_manyCollection.lastOrNullWhere((_) => _ > 10), null),
110 | );
111 | }
112 |
113 | void singleOrNullWhereTests() {
114 | test(
115 | 'Iterable.singleOrNullWhere on empty collection',
116 | () => expect(_emptyCollection.singleOrNullWhere((_) => true), null),
117 | );
118 | test(
119 | 'Iterable.singleOrNullWhere on collection with 1 element, found',
120 | () => expect(_oneItemCollection.singleOrNullWhere((_) => _ > 4), 7),
121 | );
122 | test(
123 | 'Iterable.singleOrNullWhere on collection with 1 element, not found',
124 | () => expect(_oneItemCollection.singleOrNullWhere((_) => _ < 4), null),
125 | );
126 | test(
127 | 'Iterable.singleOrNullWhere on collection with many elements, found',
128 | () => expect(_manyCollection.singleOrNullWhere((_) => _ == 3), 3),
129 | );
130 | test(
131 | 'Iterable.singleOrNullWhere on collection with many elements, too many',
132 | () => expect(_manyCollection.singleOrNull, null),
133 | );
134 | }
135 |
136 | void mapListTests() {
137 | test(
138 | 'Iterable.mapList on empty collection',
139 | () => expect(_emptyCollection.mapList((_) => _.toDouble()), []),
140 | );
141 | test(
142 | 'Iterable.mapList on collection with 1 element',
143 | () => expect(_oneItemCollection.mapList((_) => _.toDouble()), [7]),
144 | );
145 | test(
146 | 'Iterable.mapList on collection with many elements',
147 | () => expect(_manyCollection.mapList((_) => _.toDouble()),
148 | [4, 3, 6, 1, 9, 5]),
149 | );
150 | }
151 |
152 | void whereListTests() {
153 | test(
154 | 'Iterable.whereList on empty collection',
155 | () => expect(_emptyCollection.whereList((_) => _ > 4), []),
156 | );
157 | test(
158 | 'Iterable.whereList on collection with 1 element - positive',
159 | () => expect(_oneItemCollection.whereList((_) => _ > 4), [7]),
160 | );
161 | test(
162 | 'Iterable.whereList on collection with 1 element - negative',
163 | () => expect(_oneItemCollection.whereList((_) => _ < 4), []),
164 | );
165 | test(
166 | 'Iterable.whereList on collection with many elements',
167 | () => expect(_manyCollection.whereList((_) => _ > 4), [6, 9, 5]),
168 | );
169 | }
170 |
171 | void mapWhereListTests() {
172 | test(
173 | 'Iterable.mapWhereList on empty collection',
174 | () => expect(
175 | _emptyCollection.mapWhereList((_) => _.toDouble(), (_) => _ > 4),
176 | [],
177 | ),
178 | );
179 | test(
180 | 'Iterable.mapWhereList on collection with 1 element - positive',
181 | () => expect(
182 | _oneItemCollection.mapWhereList(
183 | (_) => _.toDouble(), (_) => _ > 4),
184 | [7],
185 | ),
186 | );
187 | test(
188 | 'Iterable.mapWhereList on collection with 1 element - negative',
189 | () => expect(
190 | _oneItemCollection.mapWhereList(
191 | (_) => _.toDouble(), (_) => _ < 4),
192 | [],
193 | ),
194 | );
195 | test(
196 | 'Iterable.mapWhereList on collection with many elements',
197 | () => expect(
198 | _manyCollection.mapWhereList((_) => _.toDouble(), (_) => _ > 4),
199 | [6, 9, 5],
200 | ),
201 | );
202 | }
203 |
204 | void whereMapListTests() {
205 | test(
206 | 'Iterable.whereMapList on empty collection',
207 | () => expect(
208 | _emptyCollection.whereMapList((_) => _ > 4, (_) => _.toDouble()),
209 | [],
210 | ),
211 | );
212 | test(
213 | 'Iterable.whereMapList on collection with 1 element - positive',
214 | () => expect(
215 | _oneItemCollection.whereMapList(
216 | (_) => _ > 4, (_) => _.toDouble()),
217 | [7],
218 | ),
219 | );
220 | test(
221 | 'Iterable.whereMapList on collection with 1 element - negative',
222 | () => expect(
223 | _oneItemCollection.whereMapList(
224 | (_) => _ < 4, (_) => _.toDouble()),
225 | [],
226 | ),
227 | );
228 | test(
229 | 'Iterable.whereMapList on collection with many elements',
230 | () => expect(
231 | _manyCollection.whereMapList((_) => _ > 4, (_) => _.toDouble()),
232 | [6, 9, 5],
233 | ),
234 | );
235 | }
236 |
237 | void notNullTests() {
238 | final oneItemNullCollection = [null];
239 | final manyCollection = [null, ..._manyCollection, null];
240 |
241 | test(
242 | 'Iterable.notNull on empty collection',
243 | () => expect(_emptyCollection.notNull, []),
244 | );
245 | test(
246 | 'Iterable.notNull on collection with 1 element - negative',
247 | () => expect(_oneItemCollection.notNull, [7]),
248 | );
249 | test(
250 | 'Iterable.notNull on collection with 1 element - positive',
251 | () => expect(oneItemNullCollection.notNull, []),
252 | );
253 | test(
254 | 'Iterable.notNull on collection with many elements',
255 | () => expect(manyCollection.notNull, _manyCollection),
256 | );
257 | }
258 |
259 | void groupTests() {
260 | test(
261 | 'Iterable.group on empty collection',
262 | () => expect(_emptyCollection.group((item) => item), >{}),
263 | );
264 | test(
265 | 'Iterable.group on collection with 1 element',
266 | () => expect(_oneItemCollection.group((item) => item), >{
267 | 7: [7]
268 | }),
269 | );
270 | test(
271 | 'Iterable.group on collection with many elements',
272 | () => expect(
273 | _manyCollection.followedBy([4, 4, 6, 3]).group((item) => item),
274 | >{
275 | 4: [4, 4, 4],
276 | 3: [3, 3],
277 | 6: [6, 6],
278 | 1: [1],
279 | 9: [9],
280 | 5: [5],
281 | }),
282 | );
283 | }
284 |
285 | void groupMapTest() {
286 | test(
287 | 'Iterable.groupMap on empty collection',
288 | () => expect(
289 | _emptyCollection.groupMap((item) => item, (group) => group.length),
290 | {}),
291 | );
292 | test(
293 | 'Iterable.groupMap on collection with 1 element',
294 | () => expect(
295 | _oneItemCollection.groupMap((item) => item, (group) => group.length),
296 | {7: 1}),
297 | );
298 | test(
299 | 'Iterable.groupMap on collection with many elements',
300 | () => expect(
301 | _manyCollection.followedBy([4, 4, 6, 3]).groupMap(
302 | (item) => item, (group) => group.length),
303 | {
304 | 4: 3,
305 | 3: 2,
306 | 6: 2,
307 | 1: 1,
308 | 9: 1,
309 | 5: 1,
310 | }),
311 | );
312 | }
313 |
--------------------------------------------------------------------------------
/test/src/iterable.comparable.test.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | part of '../flinq_test.dart';
6 |
7 | void iterableComparableTests() {
8 | minTests();
9 | maxTests();
10 | minOrNullTests();
11 | maxOrNullTests();
12 | minWhereTests();
13 | maxWhereTests();
14 | minOrNullWhereTests();
15 | maxOrNullWhereTests();
16 | }
17 |
18 | void minTests() {
19 | test(
20 | 'Iterable.min on empty collection',
21 | () =>
22 | expect(() => _emptyCollection.min, throwsA(TypeMatcher())),
23 | );
24 | test(
25 | 'Iterable.min on collection with 1 element',
26 | () => expect(_oneItemCollection.min, 7),
27 | );
28 | test(
29 | 'Iterable.min on collection with many elements',
30 | () => expect(_manyCollection.min, 1),
31 | );
32 | }
33 |
34 | void maxTests() {
35 | test(
36 | 'Iterable.max on empty collection',
37 | () =>
38 | expect(() => _emptyCollection.max, throwsA(TypeMatcher())),
39 | );
40 | test(
41 | 'Iterable.max on collection with 1 element',
42 | () => expect(_oneItemCollection.max, 7),
43 | );
44 | test(
45 | 'Iterable.max on collection with many elements',
46 | () => expect(_manyCollection.max, 9),
47 | );
48 | }
49 |
50 | void minOrNullTests() {
51 | test(
52 | 'Iterable.minOrNull on empty collection',
53 | () => expect(_emptyCollection.minOrNull, null),
54 | );
55 | test(
56 | 'Iterable.minOrNull on collection with 1 element',
57 | () => expect(_oneItemCollection.minOrNull, 7),
58 | );
59 | test(
60 | 'Iterable.minOrNull on collection with many elements',
61 | () => expect(_manyCollection.minOrNull, 1),
62 | );
63 | }
64 |
65 | void maxOrNullTests() {
66 | test(
67 | 'Iterable.maxOrNull on empty collection',
68 | () => expect(_emptyCollection.maxOrNull, null),
69 | );
70 | test(
71 | 'Iterable.maxOrNull on collection with 1 element',
72 | () => expect(_oneItemCollection.maxOrNull, 7),
73 | );
74 | test(
75 | 'Iterable.maxOrNull on collection with many elements',
76 | () => expect(_manyCollection.maxOrNull, 9),
77 | );
78 | }
79 |
80 | void minWhereTests() {
81 | test(
82 | 'Iterable.minWhere on empty collection',
83 | () => expect(() => _emptyCollection.minWhere((_) => _ > 4),
84 | throwsA(TypeMatcher())),
85 | );
86 | test(
87 | 'Iterable.minWhere on collection with 1 element - positive',
88 | () => expect(_oneItemCollection.minWhere((_) => _ > 4), 7),
89 | );
90 | test(
91 | 'Iterable.minWhere on collection with 1 element - negative',
92 | () => expect(() => _oneItemCollection.minWhere((_) => _ < 4),
93 | throwsA(TypeMatcher())),
94 | );
95 | test(
96 | 'Iterable.minWhere on collection with many elements',
97 | () => expect(_manyCollection.minWhere((_) => _ > 4), 5),
98 | );
99 | }
100 |
101 | void maxWhereTests() {
102 | test(
103 | 'Iterable.maxWhere on empty collection',
104 | () => expect(() => _emptyCollection.maxWhere((_) => _ > 4),
105 | throwsA(TypeMatcher())),
106 | );
107 | test(
108 | 'Iterable.maxWhere on collection with 1 element - positive',
109 | () => expect(_oneItemCollection.maxWhere((_) => _ > 4), 7),
110 | );
111 | test(
112 | 'Iterable.maxWhere on collection with 1 element - negative',
113 | () => expect(() => _oneItemCollection.maxWhere((_) => _ < 4),
114 | throwsA(TypeMatcher())),
115 | );
116 | test(
117 | 'Iterable.maxWhere on collection with many elements',
118 | () => expect(_manyCollection.maxWhere((_) => _ < 4), 3),
119 | );
120 | }
121 |
122 | void minOrNullWhereTests() {
123 | test(
124 | 'Iterable.minOrNullWhere on empty collection',
125 | () => expect(_emptyCollection.minOrNullWhere((_) => _ < 4), null),
126 | );
127 | test(
128 | 'Iterable.minOrNullWhere on collection with 1 element - positive',
129 | () => expect(_oneItemCollection.minOrNullWhere((_) => _ > 4), 7),
130 | );
131 | test(
132 | 'Iterable.minOrNullWhere on collection with 1 element - negative',
133 | () => expect(_oneItemCollection.minOrNullWhere((_) => _ < 4), null),
134 | );
135 | test(
136 | 'Iterable.minOrNullWhere on collection with many elements',
137 | () => expect(_manyCollection.minOrNullWhere((_) => _ > 4), 5),
138 | );
139 | }
140 |
141 | void maxOrNullWhereTests() {
142 | test(
143 | 'Iterable.maxOrNullWhere on empty collection',
144 | () => expect(_emptyCollection.maxOrNullWhere((_) => _ > 4), null),
145 | );
146 | test(
147 | 'Iterable.maxOrNullWhere on collection with 1 element - positive',
148 | () => expect(_oneItemCollection.maxOrNullWhere((_) => _ > 4), 7),
149 | );
150 | test(
151 | 'Iterable.maxOrNullWhere on collection with 1 element - negative',
152 | () => expect(_oneItemCollection.maxOrNullWhere((_) => _ < 4), null),
153 | );
154 | test(
155 | 'Iterable.maxOrNullWhere on collection with many elements',
156 | () => expect(_manyCollection.maxOrNullWhere((_) => _ < 4), 3),
157 | );
158 | }
159 |
--------------------------------------------------------------------------------
/test/src/iterable.math.test.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | part of '../flinq_test.dart';
6 |
7 | void iterableMathTests() {
8 | sumTests();
9 | averageTests();
10 | sumWhereTests();
11 | averageWhereTests();
12 | }
13 |
14 | void sumTests() {
15 | test(
16 | 'Iterable.sum on empty collection',
17 | () => expect(_emptyCollection.sum, 0),
18 | );
19 | test(
20 | 'Iterable.sum on collection with 1 element',
21 | () => expect(_oneItemCollection.sum, 7),
22 | );
23 | test(
24 | 'Iterable.sum on collection with many elements',
25 | () => expect(_manyCollection.sum, 28),
26 | );
27 | }
28 |
29 | void averageTests() {
30 | test(
31 | 'Iterable.average on empty collection',
32 | () => expect(_emptyCollection.average, 0),
33 | );
34 | test(
35 | 'Iterable.average on collection with 1 element',
36 | () => expect(_oneItemCollection.average, 7),
37 | );
38 | test(
39 | 'Iterable.average on collection with many elements',
40 | () => expect(_manyCollection.average, 28 / 6),
41 | );
42 | }
43 |
44 | void sumWhereTests() {
45 | test(
46 | 'Iterable.sumWhere on empty collection',
47 | () => expect(_emptyCollection.sumWhere((_) => _ > 4), 0),
48 | );
49 | test(
50 | 'Iterable.sumWhere on collection with 1 element',
51 | () => expect(_oneItemCollection.sumWhere((_) => _ > 4), 7),
52 | );
53 | test(
54 | 'Iterable.sumWhere on collection with many elements',
55 | () => expect(_manyCollection.sumWhere((_) => _ > 4), 20),
56 | );
57 | }
58 |
59 | void averageWhereTests() {
60 | test(
61 | 'Iterable.averageWhere on empty collection',
62 | () => expect(_emptyCollection.averageWhere((_) => _ > 4), 0),
63 | );
64 | test(
65 | 'Iterable.averageWhere on collection with 1 element',
66 | () => expect(_oneItemCollection.averageWhere((_) => _ > 4), 7),
67 | );
68 | test(
69 | 'Iterable.averageWhere on collection with many elements',
70 | () => expect(_manyCollection.averageWhere((_) => _ > 4), 20 / 3),
71 | );
72 | }
73 |
--------------------------------------------------------------------------------
/test/src/iterable.set.test.dart:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2021, the MarchDev Toolkit 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 | part of '../flinq_test.dart';
6 |
7 | final Iterable _manyCollectionSet = [4, 3, 6, 1, 9, 5, 3, 1, 5];
8 |
9 | void iterableSetTests() {
10 | distinctTests();
11 | unionTests();
12 | intersectionTests();
13 | differenceTests();
14 | distinctWhereTests();
15 | unionWhereTests();
16 | intersectionWhereTests();
17 | differenceWhereTests();
18 | }
19 |
20 | void distinctTests() {
21 | test(
22 | 'Iterable.distinct on empty collection',
23 | () {
24 | final actual = _emptyCollection.distinct;
25 | expect(actual is List, true);
26 | expect(actual, []);
27 | },
28 | );
29 | test(
30 | 'Iterable.distinct on collection with 1 element',
31 | () {
32 | final actual = _oneItemCollection.distinct;
33 | expect(actual is List, true);
34 | expect(actual, [7]);
35 | },
36 | );
37 | test(
38 | 'Iterable.distinct on collection with many elements',
39 | () {
40 | final actual = _manyCollectionSet.distinct;
41 | expect(actual is List, true);
42 | expect(actual, [4, 3, 6, 1, 9, 5]);
43 | },
44 | );
45 | }
46 |
47 | void unionTests() {
48 | test(
49 | 'Iterable.union on empty collection with empty collection',
50 | () {
51 | final actual = _emptyCollection.union(_emptyCollection as List);
52 | expect(actual is List, true);
53 | expect(actual, []);
54 | },
55 | );
56 | test(
57 | 'Iterable.union on empty collection with full collection',
58 | () {
59 | final actual = _emptyCollection.union(_manyCollectionSet as List);
60 | expect(actual is List, true);
61 | expect(actual, [4, 3, 6, 1, 9, 5]);
62 | },
63 | );
64 | test(
65 | 'Iterable.union on collection (1 element) with empty collection',
66 | () {
67 | final actual = _oneItemCollection.union(_emptyCollection as List);
68 | expect(actual is List, true);
69 | expect(actual, [7]);
70 | },
71 | );
72 | test(
73 | 'Iterable.union on collection (1 element) with full collection',
74 | () {
75 | final actual = _oneItemCollection.union(_manyCollectionSet as List);
76 | expect(actual is List, true);
77 | expect(actual, [7, 4, 3, 6, 1, 9, 5]);
78 | },
79 | );
80 | test(
81 | 'Iterable.union on collection (many elements) with empty collection',
82 | () {
83 | final actual = _manyCollectionSet.union(_emptyCollection as List);
84 | expect(actual is List, true);
85 | expect(actual, [4, 3, 6, 1, 9, 5]);
86 | },
87 | );
88 | test(
89 | 'Iterable.union on collection (many elements) with full collection',
90 | () {
91 | final fullCollection = [2, 4, 7, 0];
92 | final actual = _manyCollectionSet.union(fullCollection);
93 | expect(actual is List, true);
94 | expect(actual, [4, 3, 6, 1, 9, 5, 2, 7, 0]);
95 | },
96 | );
97 | }
98 |
99 | void intersectionTests() {
100 | test(
101 | 'Iterable.intersection on empty collection with empty collection',
102 | () {
103 | final actual =
104 | _emptyCollection.intersection(_emptyCollection as List);
105 | expect(actual is List, true);
106 | expect(actual, []);
107 | },
108 | );
109 | test(
110 | 'Iterable.intersection on empty collection with full collection',
111 | () {
112 | final actual =
113 | _emptyCollection.intersection(_manyCollectionSet as List);
114 | expect(actual is List, true);
115 | expect(actual, []);
116 | },
117 | );
118 | test(
119 | 'Iterable.intersection on collection (1 element) with empty collection',
120 | () {
121 | final actual =
122 | _oneItemCollection.intersection(_emptyCollection as List);
123 | expect(actual is List, true);
124 | expect(actual, []);
125 | },
126 | );
127 | test(
128 | 'Iterable.intersection on collection (1 element) with full collection',
129 | () {
130 | final fullCollection = [2, 4, 7, 0];
131 | final actual = _oneItemCollection.intersection(fullCollection);
132 | expect(actual is List, true);
133 | expect(actual, [7]);
134 | },
135 | );
136 | test(
137 | 'Iterable.intersection on collection (many elements) with empty collection',
138 | () {
139 | final actual =
140 | _manyCollectionSet.intersection(_emptyCollection as List);
141 | expect(actual is List, true);
142 | expect(actual, []);
143 | },
144 | );
145 | test(
146 | 'Iterable.intersection on collection (many elements) with full collection',
147 | () {
148 | final fullCollection = [2, 4, 7, 0, 5, 3];
149 | final actual = _manyCollectionSet.intersection(fullCollection);
150 | expect(actual is List, true);
151 | expect(actual, [4, 3, 5]);
152 | },
153 | );
154 | }
155 |
156 | void differenceTests() {
157 | test(
158 | 'Iterable.difference on empty collection with empty collection',
159 | () {
160 | final actual = _emptyCollection.difference(_emptyCollection as List);
161 | expect(actual is List, true);
162 | expect(actual, []);
163 | },
164 | );
165 | test(
166 | 'Iterable.difference on empty collection with full collection',
167 | () {
168 | final actual =
169 | _emptyCollection.difference(_manyCollectionSet as List);
170 | expect(actual is List, true);
171 | expect(actual, []);
172 | },
173 | );
174 | test(
175 | 'Iterable.difference on collection (1 element) with empty collection',
176 | () {
177 | final actual =
178 | _oneItemCollection.difference(_emptyCollection as List);
179 | expect(actual is List, true);
180 | expect(actual, [7]);
181 | },
182 | );
183 | test(
184 | 'Iterable.difference on collection (1 element) with full collection',
185 | () {
186 | final fullCollection = [2, 4, 7, 0];
187 | final actual = _oneItemCollection.difference(fullCollection);
188 | expect(actual is List, true);
189 | expect(actual, []);
190 | },
191 | );
192 | test(
193 | 'Iterable.difference on collection (many elements) with empty collection',
194 | () {
195 | final actual =
196 | _manyCollectionSet.difference(_emptyCollection as List);
197 | expect(actual is List, true);
198 | expect(actual, [4, 3, 6, 1, 9, 5]);
199 | },
200 | );
201 | test(
202 | 'Iterable.difference on collection (many elements) with full collection',
203 | () {
204 | final fullCollection = [2, 4, 7, 0, 5, 3];
205 | final actual = _manyCollectionSet.difference(fullCollection);
206 | expect(actual is List, true);
207 | expect(actual, [6, 1, 9]);
208 | },
209 | );
210 | }
211 |
212 | void distinctWhereTests() {
213 | test(
214 | 'Iterable.distinctWhere on empty collection',
215 | () {
216 | final actual = _emptyCollection.distinctWhere((_) => _ > 4);
217 | expect(actual is List, true);
218 | expect(actual, []);
219 | },
220 | );
221 | test(
222 | 'Iterable.distinctWhere on collection with 1 element - positive',
223 | () {
224 | final actual = _oneItemCollection.distinctWhere((_) => _ > 4);
225 | expect(actual is List, true);
226 | expect(actual, [7]);
227 | },
228 | );
229 | test(
230 | 'Iterable.distinctWhere on collection with 1 element - negative',
231 | () {
232 | final actual = _oneItemCollection.distinctWhere((_) => _ < 4);
233 | expect(actual is List, true);
234 | expect(actual, []);
235 | },
236 | );
237 | test(
238 | 'Iterable.distinctWhere on collection with many elements',
239 | () {
240 | final actual = _manyCollectionSet.distinctWhere((_) => _ < 4);
241 | expect(actual is List, true);
242 | expect(actual, [3, 1]);
243 | },
244 | );
245 | }
246 |
247 | void unionWhereTests() {
248 | test(
249 | 'Iterable.unionWhere on empty collection with empty collection',
250 | () {
251 | final actual = _emptyCollection.unionWhere(
252 | _emptyCollection as List, (_) => _ > 4);
253 | expect(actual is List, true);
254 | expect(actual, []);
255 | },
256 | );
257 | test(
258 | 'Iterable.unionWhere on empty collection with full collection',
259 | () {
260 | final actual = _emptyCollection.unionWhere(
261 | _manyCollectionSet as List, (_) => _ >= 4);
262 | expect(actual is List, true);
263 | expect(actual, [4, 6, 9, 5]);
264 | },
265 | );
266 | test(
267 | 'Iterable.unionWhere on collection (1 element) with empty collection',
268 | () {
269 | final actual = _oneItemCollection.unionWhere(
270 | _emptyCollection as List, (_) => _ > 4);
271 | expect(actual is List, true);
272 | expect(actual, [7]);
273 | },
274 | );
275 | test(
276 | 'Iterable.unionWhere on collection (1 element) with full collection',
277 | () {
278 | final actual = _oneItemCollection.unionWhere(
279 | _manyCollectionSet as List, (_) => _ >= 4);
280 | expect(actual is List, true);
281 | expect(actual, [7, 4, 6, 9, 5]);
282 | },
283 | );
284 | test(
285 | 'Iterable.unionWhere on collection (many elements) with empty collection',
286 | () {
287 | final actual = _manyCollectionSet.unionWhere(
288 | _emptyCollection as List, (_) => _ >= 4);
289 | expect(actual is List, true);
290 | expect(actual, [4, 6, 9, 5]);
291 | },
292 | );
293 | test(
294 | 'Iterable.unionWhere on collection (many elements) with full collection',
295 | () {
296 | final fullCollection =