DART2 Prima Plus - 第二课 - LIST
在本系列第二篇文章中,我将完全专注于列表操作。
引言
本文是学习 Dart 语言(新一代语言)系列的第二篇。Dart 团队以几乎与 .NET Core 相同的速度升级语言。随着 Flutter 将其作为应用程序开发的主要语言,我相信它很快就会成为主流。
在本文中,我将讨论 List 类型,它是普通 Array 和 C++ List 的结合体,类似于 C# 的 System.Collection.Generic.List 数据结构。
背景
我将讨论 List 类的以下属性和方法,该类在 Dart:Core 包中定义,由于 DART 是开源的,你可以在 list.dart 文件中查看其代码。我将讨论 List 类提供的以下属性。定义和声明取自 DART 网站。如果你需要了解如何创建项目,请参考本系列的第一篇文章此处。
- 任务 #1 创建- List(int length)- 创建一个给定- length的列表。
- List.filled(int length,E fill,{bool growable:false})- 创建一个给定- length的固定长度列表,并用- fill参数初始化每个位置的值。
- List.generate(int length, E generator(int index),{bool gowable:true}) - 根据- generator函数和- length参数生成一个值列表。
- List.unmodifiable(Iterable elements)- 创建一个包含所有元素的不可修改列表。
- List.from(Iterable elements,{bool growable:false})- 创建一个包含所有元素的列表。
- static List.copyRange<T>(List<T> target, int at, List<T> source, [int start, int end]): 将- source列表复制到- target,从- at开始,你还可以指定要复制的源列表的- start(包含)和- end(不包含)。
 
- 任务 #2 属性- first- 返回列表的第一个元素。
- last- 返回列表的最后一个元素。
- length- 返回列表的长度。
- reversed- 反转列表。
- isEmpty- 检查列表是否为空。
- isNotEmpty- 检查列表是否非空。
- runtimeType- 对象类型,类似于 C# 中的类型。
 
- 任务 #3 添加/删除数据- add(E value), addAll(Iterable<E> iterable)- 将值/可迭代对象添加到列表。
- asMap()- 返回列表的不可修改的 Map,键是- index,列表项是- value。
- fillRange(int start, int end, [ E fillValue ])/- Iterable<E> getRange(int start, int end)- 将从- start(包含)到- end(不包含)范围内的对象设置为给定的- fillValue/ 返回一个在从- start(包含)到- end(不包含)范围内的对象上迭代的 Iterable。
- insert(int index, E element)/ insertAll(int index, Iterable<E> iterable)- 将对象插入此列表的- index位置 / 将- iterable的所有对象插入此列表的- index位置 & 将- iterable的所有对象插入此列表的- index位置。
- setAll(int index, Iterable<E> iterable) /setRange(int start, int end, Iterable<E> iterable, [ int skipCount = 0 ])- 将- iterable的对象(跳过前- skipCount个对象)复制到列表的- start(包含)到- end(不包含)范围。
- take(int count)/takeWhile(bool test(E value)) - 返回此可迭代对象的前- count个元素的惰性可迭代对象。/ 返回满足- test的前导元素的惰性可迭代对象。
- fold<T>(T initialValue, T combine(T previousValue, E element))- 通过迭代地将集合的每个元素与现有值组合,将集合简化为单个值。
- join([String separator = "" ])- 将每个元素转换为 String 并连接字符串。
- remove(Object value)/removeAt(int index)/removeLast()- 从此列表中删除值的第一次出现 / 从此列表中删除- index位置的对象 / 弹出并返回此列表中的最后一个对象。
- removeRange(int start, int end)- 删除从- start(包含)到- end(不包含)范围内的对象。
 
- 任务 #4 查找数据和数据位置- indexOf(E element, [ int start = 0 ])- 返回此列表中- element的第一个索引。
- elementAt(int index)- 返回第- index个元素。
- lastIndexOf(E element, [ int start ])- 返回此列表中- element的最后一个索引。
- any(bool f(E element))- 检查此可迭代对象中是否有任何元素满足测试。
- sublist(int start, [ int end ])- 返回一个新列表,其中包含从- start(包含)到- end(不包含)范围内的对象。
- where(bool test(E element))- 返回一个满足谓词- test的所有元素的新惰性 Iterable。
- singleWhere(bool test(E element))- 返回满足- test的单个元素。
- firstWhere(bool test(E element), { E orElse() })- 返回满足给定谓词- test的第一个元素。
- lastWhere(bool test(E element), { E orElse() })- 返回满足给定谓词- test的最后一个元素。
- retainWhere(bool test(E element))- 从此列表中删除所有不满足- test的对象。
- removeWhere(bool test(E element))- 从此列表中删除所有满足- test的对象。
 
Using the Code
我将本教程分为四个任务,我将分别讨论每个任务。
任务 #1
在本节中,我将讨论 DART 提供的用于在 List 中创建或初始填充数据的各种创建方法,我在此处涵盖了所有 6 种方法。你可以在随附的 zip 文件中查看 creation.dart 文件以了解相同内容。
void creation()
{
// 1.0 Basic List
List<int> listOfInt = new List<int>();
// 1.1 with Length
List<int> listOfIntWithLength = new List<int>(5);
//1.2 Using List.filled when list is fixed length
List<int> listofIntFilledFixed = new List<int>.filled(5, 1);
try{
//this will throw error
listofIntFilledFixed.add(5);
}
catch(ex)
{
  print(ex);
}
// 1.2(a) using List.filled, now list is growable
List<int> listofIntFilledGrowable = new List<int>.filled(5, 1,growable:true);
listofIntFilledGrowable.add(5);
// 1.3 using List.generate, you can specify your own function to provide value to list
// => is way to write shorthand function, the list would contain 1,2,3,4,5
// as list in dart is zero index based
List<int> listofIntGenerate = new List<int>.generate(5,(int index)=> index+1);
//1.5 Using List.from, it will also have 1,2,3,4,5
List<int> listOfIntFrom = new List<int>.from(listofIntGenerate);
// 1.4 Using List.unmodifiable list with created list
List<int> listOfIntunmodifiable = new List<int>.unmodifiable(listofIntGenerate);
try{
//this will throw error
listOfIntunmodifiable.add(5);
}
catch(ex)
{
  print(ex);
}
//1.6 Using List.copyRange, you need to specify length of target before hand
List<int> listOfIntWithcopyRange = new List<int>(3);
List.copyRange(listOfIntWithcopyRange, 0, listOfIntunmodifiable,0,3);
}
我在代码本身中提供了相关的注释以演示各种代码片段。至此,我们完成了任务 #1。
任务 #2
在此任务中,我将演示 DART:List 类提供的 first、last、length、reverse、isEmpty、isNotEmpty、runtimeType 属性的使用。代码写在 property.dart 中,该文件在随附的 zip 文件中。
void properties()
{
// Create List with pre filled items : 1,2,3,4,5
List<int> listIntProperties = new List.generate(5,(int index)=>index+1,growable: true);
// Demonstrate use of first, last and length property
print("First : ${listIntProperties.first}, Last : ${listIntProperties.last} 
       and number of elements are ${listIntProperties.length}");
//-- Print list in reverse
listIntProperties.reversed.forEach((int item){ print('item ${item}');});
//-- Demonstrate use of isEmpty, isNotEmpty, and runtimeType
print("isEmpty : ${listIntProperties.isEmpty}, isNotEmpty : ${listIntProperties.isNotEmpty} 
       and ObjectTyp ${listIntProperties.runtimeType}");
}

至此,我们完成了任务 #2。
任务 #3
在此代码中,我将讨论 add(E value)、addAll(Iterable<E> iterable)、asMap()、fillRange(int start, int end, [ E fillValue ])/ Iterable<E> getRange(int start, int end)、insert(int index, E element)/ insertAll(int index, Iterable<E> iterable)。在 listadd.dart 中的 listadd() 中查找以下代码。
void listadd()
{
//-- this list will contain 1,2,3,4,5
List<int> listIntAdd = new List.generate(5,(int index)=>index+1,growable: true);
// this list will contain 10,11
List<int> listIntAdd2 = new List.generate(2,(int index)=>index+10,growable: true);
// Task 3.1 add and addAll
listIntAdd.add(6);
// List.join (Task#3.8), join all element as string, I will talking more about in its separate section.
print("After Task 3.1 add (listIntAdd)= " + listIntAdd.join(","));
listIntAdd.addAll(listIntAdd2);
print("After Task 3.1 addAll (listIntAdd) = " + listIntAdd.join(","));
//Task 3.2, converting it to map, map is key value data structure, 
//if you have C++ background, its similar to stl::map
// otherwise if you from C# background its similar to Dictionary
print("Task#3.2 asMap()");
listIntAdd2.asMap().forEach((key,value){ print("key ${key} value is ${value}");});
//Task 3.3 fillRange and getRange, here i have created list with 3 element, I would fill all with 5
List<int> listIntfillRange = new List.generate(3,(int index)=>5,growable: true);
listIntfillRange.fillRange(0, 3, 5);
print("After Task 3.3 fillRange (listIntfillRange) = " + listIntfillRange.join(","));
// Now for checking getRange, we will get data from listIntAdd, we will get range starting
// from 3rd element to 5th, so overall 2 element would be displayed
print("After Task 3.3 getRange (listIntAdd) = " + listIntAdd.getRange(3,5).join(","));
//Task 3.4 insert and insert all
// I would insert element 7 at 2nd location
listIntfillRange.insert(2,7);
print("After Task 3.4 insert (listIntfillRange) = " + listIntfillRange.join(","));
listIntfillRange.insertAll(2, listIntAdd2);
print("After Task 3.4 insertAll (listIntfillRange) with (listIntAdd2) = " + listIntfillRange.join(","));
}

对于第二个代码演示,我将讨论 setAll(int index, Iterable<E> iterable) /setRange(int start, int end, Iterable<E> iterable, [ int skipCount = 0 ])、take(int count)/takeWhile(bool test(E value))、fold<T>(T initialValue, T combine(T previousValue, E element))、remove(Object value)/removeAt(int index)/removeLast()、removeRange(int start, int end),这些代码在 listadd.dart 的 listadd2() 中。
void listadd2()
{
//-- this list will contain 1,2,3,4,5
List<int> listIntAdd = new List<int>.generate(5,(int index)=>index+1,growable: true);
// this list will contain all zero
List<int> listIntAdd2 = new List<int>.generate(5,(int index)=>0,growable: true);
//Task3.5 setAll
print("Task 3.5 Before setAll (listIntAdd2) = " + listIntAdd2.join(","));
listIntAdd2.setAll(0, listIntAdd);
print("Task 3.5 After setAll (listIntAdd2) = " + listIntAdd2.join(","));
//Task 3.6 take/takeWhile
print("Task 3.6 take (listIntAdd2) = " + listIntAdd2.take(3).join(","));
// this will take element which is smaller than 4
print("Task 3.6 takeWhile (smaller than 4) (listIntAdd2) = 
      " + listIntAdd2.takeWhile((int item) => item <= 3 ).join(","));
//Task 3.7 fold, here we will calculate sum of all element
print("Task 3.7 fold (listIntAdd2) Initial Val= " + listIntAdd2.join(","));
// here I used toString to convert resulting integer to string to be displayed with print
print("Task 3.7 fold (listIntAdd2) = " + listIntAdd2.fold(0, (prev,element)=>prev+element).toString());
//Task 3.9 remove,removeAt,removeLast
print("Task 3.9 (listIntAdd2) Initial Val= " + listIntAdd2.join(","));
//remove 5 from listIntAdd2
listIntAdd2.remove(5);
print("Task 3.9 remove (listIntAdd2) = " + listIntAdd2.join(","));
//remove from post 2 from listIntAdd2
listIntAdd2.removeAt(2);
print("Task 3.9 removeAt (listIntAdd2) = " + listIntAdd2.join(","));
//removeLast from listIntAdd2
listIntAdd2.removeLast();
print("Task 3.9 removeAt (listIntAdd2) = " + listIntAdd2.join(","));
//Task 3.10 removeRange remove first two element from list
print("Task 3.10 (listIntAdd) Initial Val= " + listIntAdd.join(","));
listIntAdd.removeRange(0, 2);
print("Task 3.10 removeAt (listIntAdd) = " + listIntAdd.join(","));
}

至此,我们完成了任务 #3。
任务 #4
在以下代码中,我将讨论 indexOf(E element, [ int start = 0 ])、elementAt(int index)、lastIndexOf(E element, [ int start ])、any(bool f(E element))、sublist(int start, [ int end ])、where(bool test(E element))。示例在 where.dart 的 listwhere() 函数中。
listwhere(){
//-- this list will contain 1,2,3,4,5,6,7,8
List<int> listIntWhere= new List<int>.generate(8,(int index)=>index+1,growable: true);
// Task 4.1 indexOf, let find index of 6, it should be 5th, as list is zero based
print("Task 4.1 indexOf (listIntWhere) InitialVal= " + listIntWhere.join(","));
print("Task 4.1 indexOf (listIntWhere)= " + listIntWhere.indexOf(6).toString());
// Task 4.2 elementAt, let find element at 5th, it should be 6, as list is zero based
print("Task 4.2 elementAt (listIntWhere) InitialVal= " + listIntWhere.join(","));
print("Task 4.2 elementAt (listIntWhere)= " + listIntWhere.elementAt(5).toString());
// Task 4.3 lastIndexOf, let create new list with duplicate value
// it will contain 0,1,2,0,1,2
List<int> listDuplicate = new List.generate(6, (int x)=> x<3?x:x-3);
print("Task 4.3 lastIndexOf (listDuplicate) InitialVal= " + listDuplicate.join(","));
print("Task 4.3 lastIndexOf (listDuplicate)= " + listDuplicate.lastIndexOf(1).toString());
// Task 4.4 any, let find does list contain item 2
print("Task 4.4 any (listDuplicate) InitialVal= " + listDuplicate.join(","));
print("Task 4.4 any (listDuplicate)= " + listDuplicate.any((int item)=>item==2).toString());
// Task 4.5 sublist, let create sublist from 3 to 6 item
print("Task 4.5 sublist (listDuplicate) InitialVal= " + listDuplicate.join(","));
print("Task 4.5 sublist (listDuplicate)= " + listDuplicate.sublist(3,6).join(","));
// Task 4.6 where, let find item divisible by 2
print("Task 4.6 where (listDuplicate) InitialVal= " + listDuplicate.join(","));
print("Task 4.6 where (listDuplicate)= " + listDuplicate.where((int item)=> item%2==0).join(","));
}

最后但并非最不重要的是,在以下代码中,我将讨论 singleWhere(bool test(E element))、firstWhere(bool test(E element), { E orElse() })、lastWhere(bool test(E element), { E orElse() })、retainWhere(bool test(E element))、removeWhere(bool test(E element))。示例在 where.dart 的 listwhere2() 函数中。
listwhere2(){
//-- this list will contain 1,2,3,4,5,6,7,8
List<int> listIntWhere= new List<int>.generate(8,(int index)=>index+1,growable: true);
// Task 4.7 singleWhere, lets find single element in the list
print("Task 4.7 singleWhere (listIntWhere) InitialVal= " + listIntWhere.join(","));
print("Task 4.7 after singleWhere (listIntWhere)= " + 
    listIntWhere.singleWhere((int item)=>item==2).toString());
try{
listIntWhere.singleWhere((int item)=>item==9);
}
catch(ex)
{
print("Task 4.7 after singleWhere (listIntWhere) (from catch) notFound = " + ex.toString());
}
// Task 4.8 firstWhere, advantage of firstWhere is that you can specify the default element
// in case element not found
// create the list, it will contain 0,1,2,3,0,1,2,3
List<int> listDuplicate = new List.generate(8, (int x)=> x<4?x:x-4);
print("Task 4.8 firstWhere (listDuplicate) InitialVal= " + listDuplicate.join(","));
print("Task 4.8 after firstWhere (listDuplicate)= " + 
listDuplicate.firstWhere((int item)=>item==2).toString());
print("Task 4.8 after firstWhere (listDuplicate) notFound (return -1)= " + 
listDuplicate.firstWhere((int item)=>item==10,orElse: ()=>-1).toString());
// Task 4.9 lastWhere, advantage of lastWhere is that you can specify the default element
// in case element not found
print("Task 4.9 lastWhere (listDuplicate) InitialVal= " + listDuplicate.join(","));
print("Task 4.9 after lastWhere (listDuplicate)= " + 
    listDuplicate.lastWhere((int item)=>item==2).toString());
print("Task 4.9 after lastWhere (listDuplicate) notFound (return -1)= " + 
    listDuplicate.lastWhere((int item)=>item==10,orElse: ()=>-1).toString());
// Task 4.10 retainWhere, retain element in list that is divisible by 2
print("Task 4.10 retainWhere (listDuplicate) InitialVal= " + listDuplicate.join(","));
listDuplicate.retainWhere((int x)=> x%2==0);
print("Task 4.10 after retainWhere (listDuplicate) = " + listDuplicate.join(","));
// Task 4.11 removeWhere, remove element in list that is not divisible by 2
print("Task 4.11 removeWhere (listIntWhere) InitialVal= " + listIntWhere.join(","));
listIntWhere.removeWhere((int x)=> x%2!=0);
print("Task 4.11 after removeWhere (listIntWhere) = " + listIntWhere.join(","));
}

至此,我们完成了任务 #4。
关注点
- 语言规范:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf
- Dart 网站:https://dart.ac.cn/
- 文章 GitHub:https://github.com/thatsalok/FlutterExample/tree/master/darttutorial2
Flutter 教程
DART 系列
历史
- 2018 年 7 月 8 日:第一个版本



