nc-photos/app/lib/iterable_extension.dart

128 lines
3.8 KiB
Dart
Raw Normal View History

import 'dart:async';
2021-07-08 20:35:32 +02:00
import 'package:flutter/foundation.dart';
2022-06-06 13:49:28 +02:00
import 'package:nc_photos/list_extension.dart';
2021-11-19 14:47:22 +01:00
import 'package:nc_photos/override_comparator.dart';
2021-04-26 12:54:57 +02:00
import 'package:tuple/tuple.dart';
2021-04-10 06:28:12 +02:00
extension IterableExtension<T> on Iterable<T> {
/// Return a new sorted list
2021-09-15 08:58:06 +02:00
List<T> sorted([int Function(T a, T b)? compare]) => toList()..sort(compare);
2021-04-10 06:28:12 +02:00
2021-07-08 20:35:32 +02:00
/// Return a new stable sorted list
2022-06-06 10:33:56 +02:00
List<T> stableSorted([int Function(T a, T b)? compare]) =>
toList()..stableSort(compare);
2021-07-08 20:35:32 +02:00
2021-04-10 06:28:12 +02:00
/// Return a string representation of this iterable by joining the result of
/// toString for each items
String toReadableString() => "[${join(', ')}]";
2021-09-15 08:58:06 +02:00
Iterable<U> mapWithIndex<U>(U Function(int index, T element) fn) sync* {
2021-04-10 06:28:12 +02:00
int i = 0;
for (final e in this) {
yield fn(i++, e);
}
}
2021-04-26 12:54:57 +02:00
Iterable<Tuple2<int, T>> withIndex() => mapWithIndex((i, e) => Tuple2(i, e));
/// Whether the collection contains an element equal to [element] using the
/// equality function [equalFn]
bool containsIf(T element, bool Function(T a, T b) equalFn) =>
any((e) => equalFn(e, element));
/// Same as [contains] but uses [identical] to compare the objects
bool containsIdentical(T element) =>
containsIf(element, (a, b) => identical(a, b));
Iterable<Tuple2<U, List<T>>> groupBy<U>({required U Function(T e) key}) {
final map = fold<Map<U, List<T>>>(
{},
(previousValue, element) =>
previousValue..putIfAbsent(key(element), () => []).add(element));
return map.entries.map((e) => Tuple2(e.key, e.value));
}
2021-08-07 22:34:44 +02:00
2021-11-19 14:47:22 +01:00
/// Return a new list with only distinct elements
List<T> distinct() {
final s = <T>{};
return where((element) => s.add(element)).toList();
}
/// Return a new list with only distinct elements determined by [equalFn]
List<T> distinctIf(
bool Function(T a, T b) equalFn, int Function(T a) hashCodeFn) {
final s = <OverrideComparator<T>>{};
return where((element) =>
s.add(OverrideComparator<T>(element, equalFn, hashCodeFn))).toList();
}
/// Invokes [action] on each element of this iterable in iteration order
/// lazily
Iterable<T> forEachLazy(void Function(T element) action) sync* {
for (final e in this) {
action(e);
yield e;
}
}
2022-06-06 12:02:54 +02:00
Future<List<U>> computeAll<U>(ComputeCallback<T, U> callback) async {
final list = asList();
if (list.isEmpty) {
return [];
} else {
return await compute(
_computeAllImpl<T, U>, _ComputeAllMessage(callback, list));
}
2022-06-06 12:02:54 +02:00
}
/// Return a list containing elements in this iterable
///
/// If this Iterable is itself a list, this will be returned directly with no
/// copying
List<T> asList() {
if (this is List) {
return this as List<T>;
} else {
return toList();
}
}
2022-07-12 22:11:27 +02:00
/// The first index of [element] in this iterable
///
/// Searches the list from index start to the end of the list. The first time
/// an object o is encountered so that o == element, the index of o is
/// returned. Returns -1 if element is not found.
int indexOf(T element, [int start = 0]) {
var i = 0;
for (final e in this) {
if (e == element) {
return i;
}
++i;
}
return -1;
}
2022-06-06 12:02:54 +02:00
}
2022-07-08 13:28:02 +02:00
extension IterableFlattenExtension<T> on Iterable<Iterable<T>> {
/// Flattens an [Iterable] of [Iterable] values of type [T] to a [Iterable] of
/// values of type [T].
///
/// This function originated in the xml package
Iterable<T> flatten() => expand((values) => values);
}
2022-06-06 12:02:54 +02:00
class _ComputeAllMessage<T, U> {
const _ComputeAllMessage(this.callback, this.data);
final ComputeCallback<T, U> callback;
final List<T> data;
}
Future<List<U>> _computeAllImpl<T, U>(_ComputeAllMessage<T, U> message) async {
final result = await Future.wait(
message.data.map((e) async => await message.callback(e)));
return result;
2021-04-10 06:28:12 +02:00
}