前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >dart collection 库(2)

dart collection 库(2)

原创
作者头像
三流之路
发布2024-08-29 13:32:46
970
发布2024-08-29 13:32:46
举报
文章被收录于专栏:Flutter

接上篇 dart collection 库,下面是 dart collection 库对一些已有类型的扩展。

ComparatorExtension

extension ComparatorExtension<T> on Comparator<T>

  • inverse:倒过来的排序器
  • then(Comparator<T> tieBreaker) → Comparator<T>:连接多个排序器,当前面的排序器认为相等时,再用后一个排序器
  • compareBy<R>(T keyOf(R)) → Comparator<R>:就是先将集合中的元素用参数的这个转换函数转换了,然后再用原来的比较器去比较转换后的值
代码语言:dart
复制
var list = ['ab', 'cd', 'def'];  
comparator(String a, String b){ // 按长度排序  
  return b.length-a.length;  
}  
print([...list]..sort(comparator)); // [def, ab, cd] 正常排序  
print([...list]..sort(comparator.inverse)); // [ab, cd, def],逆序  
  
comparator2(String a, String b){ // 字符串按 ASCII 编码排序  
  return b.compareTo(a);  
}  
print([...list]..sort(comparator.then(comparator2))); // [def, cd, ab],如果第一个比较器两个相等的话,接着用后面的比较器  
  
var list2 = ['c', 'f'];  
var list3 = ['b', 'gxyz'];  
var list4 = [list,list2,list3];  
Comparator<List> comparator3 = comparator.compareBy((List l){ // compartor3 变量范型和参数范型对应  
  return l.join(); // 返回值类型是 comparator 的范型  
});  
// list4 的元素是 List 类型,先将它用 compareBy 那参数转换成字符串 ‘defcdab’ ‘cf', 'bgxyz'
// 然后再用 comparator 去比较三个字符串的长度  
list4.sort(comparator3); // [[def, cd, ab], [b, gxyz], [c, f]]

IterableExtension

extension IterableExtension<T> on Iterable<T>

属性

  • firstOrNull:第一个元素,如果集合空就返回 null
  • lastOrNull:最后一个元素,如果集合空就返回 null
  • singleOrNull:集合唯一的元素,如果为空或者超过一个都返回 null

过滤方法

  • whereNot(bool test(T element)) → Iterable<T>:过滤出不满足参数函数判断的值
  • whereIndexed(bool test(int index, T element)) → Iterable<T>:过滤出符合条件的,带参数
  • whereNotIndexed(bool test(int index, T element)) → Iterable<T>:whereNot 和 whereIndexed 的结合
  • firstWhereOrNull(bool test(T element)) → T?:where 是过滤符合条件的集合,这个是过滤符合条件的第一个,如果没有返回 null
  • firstWhereIndexedOrNull(bool test(int index, T element)) → T?:就是在 firstWhereOrNull 基础上多一个 index
  • lastWhereOrNull(bool test(T element)) → T?:和 firstWhereOrNull 类似,只不过它返回符合过滤条件的最后一个
  • lastWhereIndexedOrNull(bool test(int index, T element)) → T?:就是在 lastWhereOrNull 基础上多一个 index
  • singleWhereOrNull(bool test(T element)) → T?:寻找唯一的元素返回,如果集合空,没找到或者不止一个,就返回 null
  • singleWhereIndexedOrNull(bool test(int index, T element)) → T?:在 singleWhereOrNull 的基础上多一个 index
  • none(bool test(T)) → bool:没有满足条件的元素时返回 true
代码语言:dart
复制
Iterable iterable = {'ab', 'def', 'Za', true, 1, 4.5, 2, false};  
iterable.sample(3); // [true, false, 4.5],随机取出 3 个元素

iterable.whereNot((value)=>value is bool); // (ab, def, Za, 1, 4.5, 2),不是 bool 类型的值

iterable.whereIndexed((index, element) {  
  return index > 2 && element.toString().length>2;  
}); // (true, 4.5, false)

iterable.whereNotIndexed((index, element) {  
  return index > 2 && element.toString().length>2;  
}); // (ab, def, Za, 1, 2) 索引小于 2 或者长度小于等于 2

iterable.firstWhereOrNull((element)=>element.toString().length==3); // def  
iterable.firstWhereIndexedOrNull((index, element)=>element.toString().length==7); // null
iterable.lastWhereOrNull((element)=>element.toString().length==3); // 4.5
iterable.singleWhereOrNull((element)=>element.toString().length==3); // false,因为有两个值长度都是 3

iterable.none((e)=>e is String); // false

排序方法

  • sorted([Comparator<T>? compare]) → List<T>:进行排序,底层调用 [...this]..sort(compare),所以它是复制一份排序后返回了新的列表,不像 sort 那样直接修改原来的列表
  • isSorted(Comparator<T> compare) → bool:是否使用指定排序器排过序里,更准确的说,应该是顺序是否符合这个排序器的定义
  • sortedBy<K extends Comparable<K>>(K keyOf(T element)) → List<T>:类似 ComparatorExtension 里的 compareBy,先将集合元素用参数的转换函数转换,然后底层用默认的比较器,即 a.compareTo(b) 去比较
  • isSortedBy<K extends Comparable<K>>(K keyOf(T element)) → bool:顺序是否符合先用转换函数转换,然后再用默认的排序器排序的结果
  • sortedByCompare<K>(K keyOf(T element), Comparator<K> compare) → List<T>:相比 sortedBy 就是使用自定义的 Comparator 而不是用默认的
  • isSortedByCompare<K>(K keyOf(T element), Comparator<K> compare) → bool:顺序是否符合先用转换函数转换,再用自定义的排序器排序的结果
代码语言:dart
复制
var sorted = iterable.sorted((v1, v2)=>v1.toString().compareTo(v2.toString()));  
print(iterable); // {ab, def, Za, true, 1, 4.5, 2, false},原集合顺序不变  
print(sorted); // [1, 2, 4.5, Za, ab, def, false, true]  
  
bool isSorted = sorted.isSorted((v1, v2)=>v1.toString().compareTo(v2.toString()));  
print(isSorted); // true  
  
keyOf(t)=>t.toString().length; // 定义一个转换函数 keyOf
// 先将元素转换成字符串长度,然后底层给两个元素排序用元素的 compareTo 方法,也不修改原集合顺序  
var sortedBy = iterable.sortedBy<num>(keyOf);  
print(sortedBy); // [1, 2, ab, Za, def, 4.5, true, false]  
print(sortedBy.isSortedBy<num>(keyOf)); // true  
  
var myComparator = ((num a, num b)=>a.compareTo(b)).inverse; // 自定义一个比较器  
var sortedByCompare = iterable.sortedByCompare<num>(keyOf, myComparator);  
print(sortedByCompare); // [false, true, def, 4.5, ab, Za, 1, 2]  
print(sortedByCompare.isSortedByCompare(keyOf, myComparator));

遍历方法

  • forEachIndexed(void action(int index, T element)) → void:带索引遍历
  • forEachWhile(bool action(T element)) → void:遍历直到 action 返回 false
  • forEachIndexedWhile(bool action(int index, T element)) → void:在 forEachWhile 的基础上带 index
  • mapIndexed<R>(R convert(int index, T element)) → Iterable<R>:在 map() 函数的基础上带 index
代码语言:dart
复制
iterable.forEachIndexed((index, element)=>print('$index is $element'));  
iterable.forEachWhile((element) { // 遍历到 true 时结果是 false,就不遍历了,注意 true 这个不符合的也遍历到了  
  print(element.toString());  
  return element is String;  
});
iterable.forEachIndexedWhile((index, element) {
  print('$index is $element');
  return element is String;
});
iterable.mapIndexed((index, element) {  
  return '$index->$element';  
}); // (0->ab, 1->def, 2->Za, 3->true, 4->1, 5->4.5, 6->2, 7->false)

累积方法

  • reduceIndexed(T combine(int index, T previous, T element)) → T:从前往后累计迭代,index 从 1 开始,第一个 previous 就是索引为 0 的元素
  • foldIndexed<R>(R initialValue, R combine(int index, R previous, T element)) → R:和 reduceIndexed 区别就是提供一个初始值,所以 index 从 0 开始
代码语言:dart
复制
iterable.expandIndexed((index, element) {  
  return [element, '$element->$index'];  
}); // (ab, ab->0, def, def->1, Za, Za->2, true, true->3, 1, ..., false, false->7)

// abdef[1]Za[2]true[3]1[4]4.5[5]2[6]false[7]
iterable.reduceIndexed((index, previous, element)=>'$previous$element[$index]');
// start===ab[0]def[1]Za[2]true[3]1[4]4.5[5]2[6]false[7]  
iterable.foldIndexed('start===', (index, previous, element)=>'$previous$element[$index]');

分组方法

  • groupFoldBy<K, G>(K keyOf(T element), G combine(G? previous, T element)) → Map<K, G>:元素用 keyOf 函数转换,作为 map 的 key,不同元素转换出来的 key 相同时,作为一组,用第二个函数将原来的值封装在一起作为值
  • groupSetsBy<K>(K keyOf(T element)) → Map<K, Set<T>>:groupFoldBy 是自己指定怎么组合,groupSetsBy 相当于特例,自动用 Set 组合
  • groupListsBy<K>(K keyOf(T element)) → Map<K, List<T>>:也是 groupFoldBy 的特例,用 List 组合
代码语言:dart
复制
var map = iterable.lastBy((t)=>t.toString().length);  
print(map); // {2: Za, 3: 4.5, 4: true, 1: 2, 5: false},2 一开始的值是 ab,然后被后面的 za 覆盖  
  
// 先用 keyOf 将所有的值转成函数第一个范型 int 的值,如果不同的值转换后结果一样的话,这些值要组合在一起  
// 用第二个函数 combine 组合,combine 的第一个参数的范型是 groupFoldBy 的第二个范型,表示相同的 key 的值组合成什么结构  
// 第二个参数的值是原来集合元素的类型,当前例子是 dynamic 的,函数返回类型是第一个参数的类型  
combine(String? previous, element) => previous==null?element.toString():'$previous-${element.toString()}';  
var map2 = iterable.groupFoldBy<int, String>(keyOf, combine);  
print(map2); // {2: ab-Za, 3: def-4.5, 4: true, 1: 1-2, 5: false},组合成字符串  
  
var map3 = iterable.groupFoldBy<int, Set<String>>(keyOf, (Set<String>? previous, element) => previous??<String>{}..add(element.toString()));  
print(map3); // {2: {ab, Za}, 3: {def, 4.5}, 4: {true}, 1: {1, 2}, 5: {false}},相同的 key 组合成  set  

var map4 = iterable.groupSetsBy(keyOf); // 内部指定了,就用 Set 去组合,groupFoldBy 的特例  
print(map4); // {2: {ab, Za}, 3: {def, 4.5}, 4: {true}, 1: {1, 2}, 5: {false}}  
  
var map5 = iterable.groupListsBy(keyOf); // 用 List 去组合  
print(map5); // {2: [ab, Za], 3: [def, 4.5], 4: [true], 1: [1, 2], 5: [false]}

分块方法

  • splitBefore(bool test(T element)) → Iterable<List<T>>:分割成块,每一块的第一个元素是用函数判断为 true 的值,然后直到再为 true,就是用返回结果判断为 true 的元素作为分界点,第一个块从第 0 个元素开始,其它块的第一个元素都是符合 test 函数判断为 true 的情况
  • splitBeforeIndexed(bool test(int index, T element)) → Iterable<List<T>>:就是把索引传进 test 函数,看这个函数用不用,如果不用它,和 splitBefore 没什么区别
  • splitAfter(bool test(T element)) → Iterable<List<T>>:和 splitBefore 倒过来,每块的最后一个元素是 test 执行为 true 的元素,最后一个块可是剩下的元素
  • splitAfterIndexed(bool test(int index, T element)) → Iterable<List<T>>:把索引传进 test 函数
  • splitBetween(bool test(T first, T second)) → Iterable<List<T>>:两个元素用 test 判断为 true 时,在这两个元素中间分隔开
  • splitBetweenIndexed(bool test(int index, T first, T second)) → Iterable<List<T>>:把索引传进 test 函数
  • slices(int length) → Iterable<List<T>>:指定长度分割切片
代码语言:dart
复制
// 分块,参数的函数为 true 的元素作为分界点,作为块的第一个元素  
iterable.splitBefore((t)=>t.toString().length==2); // ([ab, def], [Za, true, 1, 4.5, 2, false])  
iterable.splitBefore((t)=>t.toString().length==3); // ([ab], [def, Za, true, 1], [4.5, 2, false])  
// test 函数用到了 index,只有大于 2 才去判断长度是否等于 3,否则都是 false
// 所以 index <= 2 的情况肯定都在第一个块中  
iterable.splitBeforeIndexed((index, t)=>index>2?t.toString().length==3:false); // ([ab, def, Za, true, 1], [4.5, 2, false])  
  
// test 为 true 的作为块的最后一个元素  
iterable.splitAfter((t)=>t.toString().length==2); // ([ab], [def, Za], [true, 1, 4.5, 2, false])  
iterable.splitAfter((t)=>t.toString().length==3); // ([ab, def], [Za, true, 1, 4.5], [2, false])  
iterable.splitAfterIndexed((index, t)=>index>2?t.toString().length==3:false); // ([ab, def, Za, true, 1, 4.5], [2, false])  

// 前一个比后一个长的时候,从中间分隔开  
iterable.splitBetween((first,second)=>first.toString().length>second.toString().length); // ([ab, def], [Za, true], [1, 4.5], [2, false])  
// 如果在 3-4 的索引满足条件才分割  
iterable.splitBetweenIndexed((index, first, second){ // ([ab, def, Za, true], [1, 4.5, 2, false])  
  if(index>2 && index<5) {  
    return first.toString().length>second.toString().length;  
  } else {  
    return false;  
  }  
});  

iterable.slices(3); // ([ab, def, Za], [true, 1, 4.5], [2, false])

其它方法

  • sample(int count, [Random? random]) → List<T>:从原集合随机取出几个来组成列表
  • elementAtOrNull(int index) → T?:返回指定索引的元素,如果索引超出集合长度返回 null,索引必须大于等于 0,否则抛出异常
  • expandIndexed<R>(Iterable<R> expand(int index, T element)) → Iterable<R>:将一个元素扩展成一个集合,然后 combine 在一起返回新的集合
  • lastBy<K>(K key(T)) → Map<K, T>:值用转换函数转换作为 Map 的 key,原来的值作为 value,转换函数转出的 key,可能重复,前面的 value 被覆盖

IterableComparableExtension

extension IterableComparableExtension<T extends Comparable<T>> on Iterable<T>

相当于 IterableExtension 的特例,集合的元素要是可比较的。

  • max/min:找出集合中最大最小值,如果集合为空,抛出异常
  • maxOrNull:找出集合中最大最小值,如果集合为空,返回 null
  • isSorted([Comparator<T>? compare]) → bool:是否按比较器进行排序过,和 IterableExtension 的 isSorted 区别是它的参数是可选的,因为会有一个默认的比较器

IterableNumberExtension/IterableDoubleExtension/IterableIntegerExtension

extension IterableNumberExtension on Iterable<num>

extension IterableDoubleExtension on Iterable<double>

extension IterableIntegerExtension on Iterable<int>

IterableComparableExtension 针对 num 类型的特殊扩展,num 本身也是实现了 Comparable,所以原来扩展的方法也都能用。

  • max/min/maxOrNull/minOrNull:如果有一个值是 double.nan,结果就是 NaN
  • sum:求和,集合为空,返回 0,如果有一个值是 double.nan,结果就是 NaN
  • average:求平均值,集合为空,抛出异常,如果有一个值是 double.nan,结果就是 NaN。除了 average 是 double 类型其它都是 num 类型

IterableDoubleExtensionIterableIntegerExtension 相当于 IterableComparableExtension 的特殊情况,就是这些扩展属性的类型不一样,average 都是 double 类型,别的属性分别是 num、double、int 类型。

IterableIterableExtension

extension IterableIterableExtension<T> on Iterable<Iterable<T>>

  • flattened:展开打开到一个集合
代码语言:dart
复制
Iterable<Iterable<int>> iterable = {[1,3,5], {2,4,6}};  
print(iterable.flattened); // (1, 3, 5, 2, 4, 6)

IterableNullableExtension

extension IterableNullableExtension<T extends Object> on Iterable<T?>

  • whereNotNull():过滤掉 null 值
代码语言:dart
复制
print({1,2,null,5,6}.whereNotNull()); // (1, 2, 5, 6)

ListExtensions

extension ListExtensions<E> on List<E>

和 IterableExtension 的同名方法,只是实现有所不同:

  • forEachIndexed()
  • forEachWhile()
  • forEachIndexedWhile()
  • mapIndexed()
  • whereIndexed()
  • whereNotIndexed()
  • expandIndexed()
  • elementAtOrNull()
  • slices()

二分查找:

  • binarySearch(E element, int compare(E, E)) → int:列表要符合第二个比较器的排序,二分查找索引
  • binarySearchByCompare<K>(E element, K keyOf(E element), int compare(K, K), [int start = 0, int? end]) → int:列表元素经过 keyOf 转换后符合第三个参数比较器的排序,然后二分查找索引,start 和 end(不包含) 意思就是要找的元素得在这两个索引之间,如果不在返回 -1
  • binarySearchBy<K extends Comparable<K>>(E element, K keyOf(E element), [int start = 0, int? end]) → int:和 binarySearchByCompare 对比就是不用参数传递比较器,用默认的 a.compareTo(b)
  • lowerBound(E element, int compare(E, E)) → int:类似 binarySearch,如果元素在列表中存在,返回位置,如果不存在,返回它应该插入的位置。也是用二分查找
  • lowerBoundByCompare<K>(E element, K keyOf(E), int compare(K, K), [int start = 0, int? end]) → int:和 lowerBound 的关系类似 binarySearchByCompare 和 binarySearch 的关系,也是用 keyOf 转换后要符合 compare 的关系
  • lowerBoundBy<K extends Comparable<K>>(E element, K keyOf(E), [int start = 0, int? end]) → int:和 lowerBoundByCompare 的关系类似 binarySearchBy 和 binarySearchByCompare 的关系
代码语言:dart
复制
List<int> list = [1,3,6,7];  
// 第二个参数指定的关系是从小到大
list.binarySearch(3, (a,b)=>a-b); // 1

list.binarySearchByCompare(6, (e)=>10-e, (a,b)=>b-a); // 2
list.binarySearchByCompare(6, (e)=>10-e, (a,b)=>b-a, 0, 2); // -1

list.lowerBound(4, (a,b)=>a-b); // 2

排序:

  • sortByCompare<K>(K keyOf(E element), int compare(K a, K b), [int start = 0, int? end]) → void:和 IterableExtension 的 sortedByCompare 对比,就是底层用快速排序,并且多了 start/end 参数
  • sortBy<K extends Comparable<K>>(K keyOf(E element), [int start = 0, int? end]) → void:和 IterableExtension 的 sortedBy 对比,就是底层用快速排序,并且多了 start/end 参数
  • sortRange(int start, int end, int compare(E a, E b)) → void:使用快速排序对指定索引范围内的元素进行排序
  • shuffleRange(int start, int end, [Random? random]) → void:指定范围内随机排序
  • reverseRange(int start, int end) → void:对指定范围内逆序
代码语言:dart
复制
List<int> list = [1,3,2,9,5,7,0];  
list.sortRange(1, 5, (a,b)=>a-b); // [1, 2, 3, 5, 9, 7, 0]
list.shuffleRange(1, 5);
list.reverseRange(1, 5); // [1, 5, 9, 2, 3, 7, 0],3,2,9,5 倒转顺序
  • swap(int index1, int index2) → void:交换两个元素
  • slice(int start, [int? end]) → ListSlice<E>:切片,就是取子集
  • equals(List<E> other, [Equality<E> equality = const DefaultEquality()]) → bool:和另一个集合判断是否相等,和 ListEquality().equals(a,b) 效果一样
代码语言:dart
复制
list.slice(1,5); // [3, 2, 9, 5]

ListComparableExtensions

extension ListComparableExtensions<E extends Comparable<E>> on List<E>

是 ListExtensions 的特殊版本,用于元素实现了 Comparable 的 List。

binarySearch()lowerBound()sortRange() 三个特殊方法,和 ListExtensions 的同名方法的区别就是因为元素是 Comparable 的,不需要一定要传一个比较器,可以使用默认的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ComparatorExtension
  • IterableExtension
    • 属性
      • 过滤方法
        • 排序方法
          • 遍历方法
            • 累积方法
              • 分组方法
                • 分块方法
                  • 其它方法
                  • IterableComparableExtension
                  • IterableNumberExtension/IterableDoubleExtension/IterableIntegerExtension
                  • IterableIterableExtension
                  • IterableNullableExtension
                  • ListExtensions
                  • ListComparableExtensions
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档