├── .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 | ![Build](https://github.com/marchdev-tk/flinq/workflows/build/badge.svg) 4 | [![codecov](https://codecov.io/gh/marchdev-tk/flinq/branch/master/graph/badge.svg)](https://codecov.io/gh/marchdev-tk/flinq) 5 | [![Pub](https://img.shields.io/pub/v/flinq.svg)](https://pub.dartlang.org/packages/flinq) 6 | ![GitHub](https://img.shields.io/github/license/marchdev-tk/flinq) 7 | ![GitHub stars](https://img.shields.io/github/stars/marchdev-tk/flinq?style=social) 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 = [2, 4, 7, 0]; 297 | final actual = 298 | _manyCollectionSet.unionWhere(fullCollection, (_) => _ >= 4); 299 | expect(actual is List, true); 300 | expect(actual, [4, 6, 9, 5, 7]); 301 | }, 302 | ); 303 | } 304 | 305 | void intersectionWhereTests() { 306 | test( 307 | 'Iterable.intersectionWhere on empty collection with empty collection', 308 | () { 309 | final actual = _emptyCollection.intersectionWhere( 310 | _emptyCollection as List, (_) => _ >= 4); 311 | expect(actual is List, true); 312 | expect(actual, []); 313 | }, 314 | ); 315 | test( 316 | 'Iterable.intersectionWhere on empty collection with full collection', 317 | () { 318 | final actual = _emptyCollection.intersectionWhere( 319 | _manyCollectionSet as List, (_) => _ >= 4); 320 | expect(actual is List, true); 321 | expect(actual, []); 322 | }, 323 | ); 324 | test( 325 | 'Iterable.intersectionWhere on collection (1 element) with empty collection', 326 | () { 327 | final actual = _oneItemCollection.intersectionWhere( 328 | _emptyCollection as List, (_) => _ >= 4); 329 | expect(actual is List, true); 330 | expect(actual, []); 331 | }, 332 | ); 333 | test( 334 | 'Iterable.intersectionWhere on collection (1 element) with full collection', 335 | () { 336 | final fullCollection = [2, 4, 7, 0]; 337 | final actual = 338 | _oneItemCollection.intersectionWhere(fullCollection, (_) => _ >= 4); 339 | expect(actual is List, true); 340 | expect(actual, [7]); 341 | }, 342 | ); 343 | test( 344 | 'Iterable.intersectionWhere on collection (many elements) with empty collection', 345 | () { 346 | final actual = _manyCollectionSet.intersectionWhere( 347 | _emptyCollection as List, (_) => _ >= 4); 348 | expect(actual is List, true); 349 | expect(actual, []); 350 | }, 351 | ); 352 | test( 353 | 'Iterable.intersectionWhere on collection (many elements) with full collection', 354 | () { 355 | final fullCollection = [2, 4, 7, 0, 5, 3]; 356 | final actual = 357 | _manyCollectionSet.intersectionWhere(fullCollection, (_) => _ >= 4); 358 | expect(actual is List, true); 359 | expect(actual, [4, 5]); 360 | }, 361 | ); 362 | } 363 | 364 | void differenceWhereTests() { 365 | test( 366 | 'Iterable.differenceWhere on empty collection with empty collection', 367 | () { 368 | final actual = _emptyCollection.differenceWhere( 369 | _emptyCollection as List, (_) => _ >= 4); 370 | expect(actual is List, true); 371 | expect(actual, []); 372 | }, 373 | ); 374 | test( 375 | 'Iterable.differenceWhere on empty collection with full collection', 376 | () { 377 | final actual = _emptyCollection.differenceWhere( 378 | _manyCollectionSet as List, (_) => _ >= 4); 379 | expect(actual is List, true); 380 | expect(actual, []); 381 | }, 382 | ); 383 | test( 384 | 'Iterable.differenceWhere on collection (1 element) with empty collection', 385 | () { 386 | final actual = _oneItemCollection.differenceWhere( 387 | _emptyCollection as List, (_) => _ >= 4); 388 | expect(actual is List, true); 389 | expect(actual, [7]); 390 | }, 391 | ); 392 | test( 393 | 'Iterable.differenceWhere on collection (1 element) with full collection', 394 | () { 395 | final fullCollection = [2, 4, 7, 0]; 396 | final actual = 397 | _oneItemCollection.differenceWhere(fullCollection, (_) => _ >= 4); 398 | expect(actual is List, true); 399 | expect(actual, []); 400 | }, 401 | ); 402 | test( 403 | 'Iterable.differenceWhere on collection (many elements) with empty collection', 404 | () { 405 | final actual = _manyCollectionSet.differenceWhere( 406 | _emptyCollection as List, (_) => _ >= 4); 407 | expect(actual is List, true); 408 | expect(actual, [4, 6, 9, 5]); 409 | }, 410 | ); 411 | test( 412 | 'Iterable.differenceWhere on collection (many elements) with full collection', 413 | () { 414 | final fullCollection = [2, 4, 7, 0, 5, 3]; 415 | final actual = 416 | _manyCollectionSet.differenceWhere(fullCollection, (_) => _ >= 4); 417 | expect(actual is List, true); 418 | expect(actual, [6, 9]); 419 | }, 420 | ); 421 | } 422 | --------------------------------------------------------------------------------