Flutter開發之Dart的資料型別01
- 這幾篇文章都是在學習
Dart
過程中所記錄的學習筆記, 都是一些基礎知識, 幾乎沒什麼技術含量, 主要是方便後期使用的時候方便查閱 - 我寫的 Flutter和Dart語法系列相關的文章 , 有興趣的可參考隨便看看
Dart資料型別
Dart
內建的資料型別中, 支援以下幾種資料型別
-
numbers
(數字) -
strings
(字串) -
booleans
(布林) -
lists
(也被稱之為arrays
) -
maps
-
runes
(用於在字串中表示Unicode
字元) -
symbols
上面的資料型別可以直接使用字面量初始化
var str = 'this is a string' ; var isStr = true;
也可以使用建構函式初始化, 由於 Dart
中每個變數引用的都是一個物件 – 一個類的例項, 一些內建的型別具有自己的建構函式
// 可以使用 Map()建構函式來建立一個 map,就像這樣 var map = new Map();
Dart
中 Numbers
支援兩種型別的數字:
-
int
: 整數值,其取值通常位於-2^53
和2^53
之間, 差不多9*10^16
, 也就是支援16位數字 -
double
:64-bit
(雙精度) 浮點數,符合IEEE 754
標準
int
- 其取值通常位於
-2^53
和2^53
之間 - 也就是-9,007,199,254,740,992和9,007,199,254,740,992之間
- 實際在編譯中則是超過19位則會報錯
- 更多可參考 問題 1533 瞭解更多資訊
// 如下定義則會報錯, 定義的int星變數需要在9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808之間 var bil = 12345678901234567890;
一些常用的判斷屬性
const m1 = 12; // 是否為負數, 大於0即為false print(m1.isNegative); print(0.isNegative); // 是否是有限的 print(b32.isFinite); print(m1.isFinite); // 是否是無窮大或者無窮小 print(m1.isInfinite); // 是否為偶數 print(m1.isEven); // 是否為奇數 print(m1.isOdd); // 是否是NaN值 print(m1.isNaN); // 資料的符號,-1.0:值小於0、+1.0:值大於0、-0.0/0.0/NaN:值是其本身 print(21.sign);// 1 print(-23.sign); // -1 print(0.sign);// 0 print(-0.sign);// 0
int
數字型別中常用的函式
const m3 = 24; // 獲取絕對值 print(m3.abs()); // 轉成字串 print(m3.toString()); // 冪次求模; m3的4次冪, 在對3求模 print(m3.modPow(4, 3)); // 1 // 返回m3和16的最大公約數 print(m3.gcd(16)); // 返回m3除以5的餘數 print(m3.remainder(5)); // 轉成double print(m3.toDouble()); // 比較大小, 0:相同、1:大於、-1:小於 print(m3.compareTo(30));
double
下面是定義 double
的一些方式:
var y = 1.1; var exponents = 1.42e5;
double
型別相關的屬性使用
// 是否是NaN值 print(d0.isNaN); // 是否是無窮大或者無窮小 print(d0.isInfinite); // 是否是有限的 print(d0.isFinite); // 是否為負數, 大於0即為false print(d0.isNegative); // 根據程式碼單元生成的雜湊碼 print(d0.hashCode); // 資料的符號,-1.0:值小於0、+1.0:值大於0、-0.0/0.0/NaN:值是其本身 print(d0.sign); print(-1.23.sign); print(0.0.sign); // 返回執行時的型別 print(d0.runtimeType);// double
double
型別相關方法的使用
// 轉成字串 print(d0.toString()); // 取整數, 小數點捨去 print(d0.toInt()); // 比較大小, 0:相同、1:大於、-1:小於 print(d0.compareTo(30)); // 獲取絕對值 print(d0.abs()); // 四捨五入 print(d0.round()); // 13 // 向上取整 print(d0.ceil());// 14 // 向下取整 print(d0.floor()); // 13 // 輸出的double型別, 相當於d0.round().toDouble() print(d0.roundToDouble()); // 13.0 print(d0.ceilToDouble());// 14.0 print(d0.floorToDouble()); // 13.0 // 保留指定的小數位數(四捨五入), 不足補0, 字串返回 print(d0.toStringAsFixed(2)); // 13.10 // 保留變數的位數(小數點前後的總位數), 不足補0, 多餘的四捨五入 print(d0.toStringAsPrecision(10));// 13.09870000 /**toStringAsExponential *1.toStringAsExponential();// 1e+0 *1.toStringAsExponential(3);// 1.000e+0 *123456.toStringAsExponential();// 1.23456e+5 *123456.toStringAsExponential(3); // 1.235e+5 *123.toStringAsExponential(0);// 1e+2 */ /** toStringAsPrecision *1.toStringAsPrecision(2);// 1.0 *1e15.toStringAsPrecision(3);// 1.00e+15 *1234567.toStringAsPrecision(3); // 1.23e+6 *1234567.toStringAsPrecision(9); // 1234567.00 *12345678901234567890.toStringAsPrecision(20); // 12345678901234567168 *12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19 *0.00000012345.toStringAsPrecision(15); // 1.23450000000000e-7 *0.0000012345.toStringAsPrecision(15);// 0.00000123450000000000 */
Booleans
- 為了代表布林值,
Dart
有一個名字為bool
的型別。 - 只有兩個物件是布林型別的:
true
和false
所建立的物件, 這兩個物件也都是編譯時常量 - 當
Dart
需要一個布林值的時候,只有true
物件才被認為是true
, 所有其他的值都是flase
; 像 1、"aString"
、 以及someObject
等值都被認為是false
const m = 1; if (m) { print('是一個布林值'); } else { print('不是一個布林值'); }
- 在
Dart
中上面判斷語句是合法的程式碼 - 但是在
Dart
檢查模式執行,上面的程式碼將會丟擲一個異常,表示m
變數不是一個布林值 - 所以不建議這麼使用上述方法進行判斷
Strings
Dart
字串是 UTF-16
編碼的字元序列, 可以使用單引號或者雙引號來建立字串:
var s1 = 'Single quotes work well for string literals.'; var s2 = "Double quotes work just as well."; // 單引號裡面有單引號(雙引號裡面有雙引號)時, 必須使用反斜\槓轉義 var s3 = 'It\'s easy to escape the string delimiter.'; var s4 = "It's even easier to use the other delimiter.";
字串的拼接
直接把相鄰字串寫在一起,就可以連線字串了
var string = 'name''+''age'
用+把相鄰字串連線起來
var string1 = 'name' + '+' + 'age';
引用變數
- 在
Dart
中使用$
符號引用變數或者表示式 - 表示式引用方式:
${表示式}
, 如果表示式是一個變數則{}
可以省略
const num1 = 12; // 引用表示式 const ageStr0 = 'age = $num1'; const ageStr1 = 'age = ${num1} is my age'; // 引用表示式 const ageStr2 = 'age = ${num1 * num1}';
多行字串
使用單引號或雙引號的三引號
const line1 = ''' 道路千萬條,安全第一條, 行車不規範,親人兩行淚 '''; const line2 = """ 道路千萬條,安全第一條, 行車不規範,親人兩行淚 """;
轉義符號
宣告 raw字串(字首為r)
,在字串前加字元 r
,或者在 \
前面再加一個 \
,可以避免 \
的轉義作用,在正則表示式裡特別有用
// 轉義字元 print(r'轉義字元, \n'); print('轉義字元, \\n'); print('轉義字元, \n');
屬性介紹
const string0 = 'https://www.titanjun.top/'; // 可根據索引獲取字串的每一個字元 print(string0[1]); // 字串是否是空的 print(string0.isEmpty); print(''.isEmpty); // true // 字串是否不是空的 print(string0.isNotEmpty); print(''.isNotEmpty);// false // 返回字串Unicode程式碼的可迭代物件 print(string0.runes); // 返回字串的UTF-16程式碼單元列表 print(string0.codeUnits); // 返回根據程式碼單元生成的雜湊碼 print(string0.hashCode); // 字串的長度 print(string0.length); // 返回物件執行時的型別 print(string0.runtimeType);// String
方法介紹
const string0 = 'https://www.titanjun.top/'; // 字串比較 print('titan'.compareTo('jun')); // 大小寫轉換 print(string0.toUpperCase()); print(string0.toLowerCase()); // 擷取字串(開頭索引和結尾索引) print(string0.substring(0, 5)); // https // 只有開頭索引, 預設擷取到最後 print(string0.substring(12));// titanjun.top/ // 拆分字串 print(string0.split('.'));// [https://www, titanjun, top/] print(string0.split(new RegExp(r"t")));// [h, , ps://www., i, anjun., op/] // 去掉字串裡面的tab空格和換行符 const string1 = '\t\ttitanjun top\n'; print(string1.trim()); // 去掉字串開頭的tab空格和換行符 print(string1.trimLeft()); // 去掉字串結尾的tab空格和換行符 print(string1.trimRight());
endsWith
判斷字串是否以某字元(字串)結尾, 引數不接受正則表示式
const str1 = 'titanjun.top'; print(str1.endsWith('p'));//true print(str1.endsWith('/'));//false print(str1.endsWith('top'));//true
startsWith
bool startsWith(Pattern pattern, [int index = 0]);
判斷字串是否以某字元(字串)開頭, 引數接受正則表示式
const str1 = 'titanjun.top'; print(str1.startsWith('h'));//false print(str1.startsWith('tit')); //true print(str1.startsWith('it', 1)); //true print(str1.startsWith(new RegExp(r'[A-Z][a-z]'), 1)); //false
indexOf
int indexOf(Pattern pattern, [int start]);
- 根據指定的字元(字串)獲取其在原字串中第一次出現的索引值, 順序是從左到右
- 可以從指定的索引初開始, 預設從0開始
- 如果原字串中沒有需要查詢的字元(字串), 則返回值為: -1
const str2 = 'https://www.titanjun.top/'; print(str2.indexOf('titan')); // 12 print(str2.indexOf('t', 5));// 12 print(str2.indexOf(new RegExp(r'[a-z]'))); //0 // 如果沒有改字元, 則會輸出-1 print(str2.indexOf('ppp'));// -1
lastIndexOf
int lastIndexOf(Pattern pattern, [int start]);
效果和 indexOf
一樣, 不同點則是: indexOf
的順序是從左到右, lastIndexOf
是從右到左
const str2 = 'https://www.titanjun.top/'; print(str2.lastIndexOf('t', 20));//14 print(str2.indexOf(new RegExp(r'[a-z]'))); //0 // 如果沒有改字元, 則會輸出-1 print(str2.indexOf('ppp'));// -1
補佔位符
String padLeft(int width, [String padding = ' ']); String padRight(int width, [String padding = ' ']);
- 在字串前後補佔位符
- 引數一: 想要得到的字串的位數
- 引數二: 位數不足時, 補充的字元
const str3 = '12'; print(str3.padLeft(2, '0')); //12 print(str3.padRight(3, '0')); // 120
contains
bool contains(Pattern other, [int startIndex = 0]);
- 判斷字串中是否包含某字元
- 判斷指定索引處的字元是否是某字元
bool contains(Pattern other, [int startIndex = 0]); const str = 'Dart strings'; print(str.contains('D')); print(str.contains(new RegExp(r'[A-Z]'))); print(str.contains('D', 0)); print(str.contains(new RegExp(r'[A-Z]'), 0));
替換字元
// 只能替換一次, 引數三為開始的索引值, 預設0 String replaceFirst(Pattern from, String to, [int startIndex = 0]); // 替換所有符合條件的字元(字串) String replaceAll(Pattern from, String replace); // 替換某一區間的字元 String replaceRange(int start, int end, String replacement); // 示例如下: // 替換字串 const str4 = 'titanjun12--0123'; print(str4.replaceFirst('t', 'T'));// Titanjun12--0123 print(str4.replaceFirst('12', '21', 10));//titanjun12--0213 // 全部替換 print(str4.replaceAll('12', '21'));//titanjun21--0213 print(str4.replaceAll('t', 'T'));//TiTanjun12--0123 // 區間替換 print(str4.replaceRange(0, 5, 'top'));//topjun12--0123
List
在 Dart
中 List
物件就是其他語言中的陣列
建立陣列
// 建立一個指定長度的List, 不能新增/刪除元素 List([int length]); //通過指定長度建立一個固定長度的List,並使用fill初始化每個位置的值, 不能新增/刪除元素 List.filled(int length, E fill, {bool growable: false}); //建立一個包含所有elements的List, //當growable為true(預設)時,建構函式返回一個可增長的List。 否則,它返回一個固定長度的List List.from(Iterable elements, {bool growable: true}) //生成一個包含所有值的List //除非growable為true(預設),否則建立的List是固定長度的 List.generate(int length, E generator(int index), {bool growable: true}) //建立一個包含所有elements的,不能改變它的長度或元素 List.unmodifiable(Iterable elements)
List
- 如果設定了引數
length
(length
不能為負數或null
),那麼建立的List
是固定長度的 - 元素可修改, 元素個數不可修改, 不能刪除和增加元素
var l1 = new List(3);//[null, null, null] print(l1.length);//3 // 下面這種寫法會報錯 l1.length = 1;
如果未設定引數 length
,那麼 List
的長度是0,並且是可增長的
// 這兩種方式一樣 var l10 = new List(); var l11 = []; // 都是可行的 l10.length = 3; l10.add(1);
當使用指定長度建立一個可增長的 List
時,僅僅在剛建立後分配長度
List growableList = new List()..length = 500;
filled
- 通過指定長度建立一個固定長度的
List
,並初始化每個位置的值 - 所有的元素都是相同的
fill
值。 如果指定的值是一個可變物件,那麼List
中所有的元素都是相同的物件,並且是可修改的
var l2 = new List.filled(3, 'l');//[l, l, l] var l3 = new List.filled(2, []);// [[], []] l3[0].add(12); print(l3);// [[12], [12]]
from
- 建立一個包含所有
elements
的List
-
elements
的Iterator
規定了元素的順序。 - 當
growable
為true
(預設)時,建構函式返回一個可增長的List
。 否則,它返回一個固定長度的List
var l5 = new List.from([1, 2, 3, 4]); l5.add(5); print(l5);// [1, 2, 3, 4, 5] // 下面的add方法會報錯 var l5 = new List.from([1, 2, 3, 4], growable: false); l5.add(5);
generate
- 生成一個包含所有值的
List
, 根據索引值建立元素 -
growable
為false
時,建立的List
是固定長度的
var l4 = new List.generate(3, (int i) => i * i); l4.add(14); print(l4); // [0, 1, 4, 14]
unmodifiable
- 建立一個包含所有
elements
的,不可修改的List
- 不可修改的
List
不能改變它的長度或元素 - 如果元素本身是不可改變的,那麼由此產生的
List
也是不可改變的
var l6 = new List.unmodifiable([1, 2, 3, 4]);
List屬性
var arr1 = [1, 2, 3, 4]; // 陣列的第一個和最後一個元素 print(arr1.first);// 1 print(arr1.last);// 4 // 判斷陣列是否為空 print(arr1.isNotEmpty);// true print(arr1.isEmpty);// false // 陣列長度, 元素個數 print(arr1.length);// 4 // 倒序返回List print(arr1.reversed);// [4, 3, 2, 1] // 返回Iterator,被允許迭代Iterable的所有元素 print(arr1.iterator); // 物件的執行時型別 print(arr1.runtimeType);// List<int> // 獲取物件的雜湊值 print(arr1.hashCode); // 根據索引獲取元素 print(arr1[2]); // 根據索引修改元素 arr1[1] = 11; print(arr1);
List方法
增加
// 新增元素 arr1.add(5); // 新增一個數組 arr1.addAll([10, 12]);
查詢
var arr2 = ['one', 'two', 'three', 'one', 'four']; // 是否包含某元素 print(arr2.contains('one'));// true // 判斷陣列是否有滿足條件的元素 print(arr2.any((item) => item.length > 4));// true // 判斷陣列是否所有元素都滿足條件 print(arr2.every((item) => item.length > 4));// false // 轉化為Map型別, 索引作為Key值,對應的元素作為Value print(arr2.asMap());// {0: one, 1: two, 2: three, 3: one, 4: four} //隨機打亂List中的元素 arr2.shuffle(); // 通過索引獲取元素, 等價於arr2[3] print(arr2.elementAt(3)); // 獲取元素對應的索引值, 預設從索引0開始 print(arr2.indexOf('one'));// 0 // 從第2個索引開始查詢 print(arr2.indexOf('one', 2));// 3 // 如果找不到, 返回-1 print(arr2.indexOf('five'));// -1 // 獲取元素對應的索引值, 從後往前找 print(arr2.lastIndexOf('one')); print(arr2.lastIndexOf('one', 3)); print(arr2.lastIndexOf('five')); // 返回滿足條件的第一個元素 print(arr3.firstWhere((item) => item == 'one')); // 查詢符合條件的元素, 如果有且僅有一個符合條件的元素, 則返回該元素 // 如果沒有匹配到元素,或匹配到多個元素, 則會丟擲異常 print(arr2.singleWhere((item) => item.length == 5));//three // 返回除了最初的count個元素外的所有元素 arr2 = ['one', 'two', 'three', 'four']; print(arr2.skip(2)); // (three, four) // 返回所有不符合該條件的元素 print(arr2.skipWhile((item) => item.length == 3));//(three, four) // 返回一個新的List,包含從start(包括)到end(不包括)的物件, 原陣列不變 print(arr2.sublist(1, 3)); // 不指定end, 預設到陣列結尾 print(arr2.sublist(2)); // 獲取某一區間的元素, 返回一個數組 print(arr2.getRange(1, 3));// ['two', 'three'] // 陣列拼接成字串 print(arr2.join());//onetwothreefour print(arr2.join('-'));//one-two-three-four // 返回陣列最初的count個元素 print(arr2.take(2)); // 返回陣列符合條件的元素, 直到條件值為false停止過濾 arr2 = ['one', 'two', 'three', 'four', 'ten']; print(arr2.takeWhile((item) => item.length == 3));//(one, two)
刪除
var arr2 = ['one', 'two', 'three', 'one', 'four']; // 刪除指定的元素 // 如果有該元素, 返回true print(arr2.remove('two'));// true print(arr2);// [one, three, one, four] // 如果沒有該元素, 返回false print(arr2.remove('five'));// false // 根據索引刪除, 返回被刪除的元素值 print(arr2.removeAt(1));// three print(arr2);// [one, one, four] // 刪除最後一個元素, 返回該元素值 print(arr2.removeLast());// four print(arr2); // [one, one] // 刪除一個區間的元素, 含左不含右[start, end) arr2.addAll(['six', 'seven', 'eight']); arr2.removeRange(1, 3); print(arr2);// [one, seven, eight] // 刪除所有符合條件的元素 arr2.removeWhere((item) => item.length == 3); print(arr2);// [seven, eight] //刪除List中所有不滿足條件的元素 arr2.retainWhere((item) => item.length > 3); print(arr2); // 刪除所有的元素 arr1.clear(); print(arr1);// []
插入
var arr3 = [1, 3, 4]; // 在某處插入元素 arr3.insert(1, 10); print(arr3); //[1, 10, 3, 4] // 插入一個數組 arr3.insertAll(2, [12, 32]); print(arr3);
重要方法
//過濾 Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test); // 對映 Iterable<T> map<T>(T f(E e)) => new MappedIterable<E, T>(this, f); // 排序 void sort([int compare(E a, E b)]); // 迭代計算, initialValue: 初始值, combine: 計算函式 T fold<T>(T initialValue, T combine(T previousValue, E element)) // 迭代計算, 初始值即為第一個元素的值, combine: 計算函式 E reduce(E combine(E value, E element)) // 對集合的每個元素,按迭代順序執行函式操作 void forEach(void f(E element)) // 將Iterable的每個元素擴充套件為0個或多個元素 Iterable expand(Iterable f(E element))
下面看一下每一個函式的具體使用和介紹
var arr2 = ['one', 'two', 'three', 'four']; // 過濾操作, 返回所有符合條件的元素 print(arr2.where((item) => item.length == 3));//(one, two, ten) // 對映一個新的陣列, 引數是一個函式 var array = arr2.map((item) { return item + '-'; }); print(array.toList());// [one-, ten-, two-, four-, three-] // 排序, 預設從小到大 arr2.sort(); print(arr2);//[four, one, ten, three, two] // 設定條件進行排序 arr2.sort((item1, item2) { // 如果兩個比較的結果為0, 那麼排序後返回的結果可能不同 return item1.length.compareTo(item2.length); }); print(arr2);//[one, ten, two, four, three] // 迭代計算, initialValue: 初始值, combine: 計算函式 var arr4 = [1, 2, 3, 4]; // 設定初始值 var result1 = arr4.fold(10, (prev, value) => prev + value);//20 var result2 = arr4.fold(2, (prev, value) => prev * value);//48 // 初始值即為第一個元素的值, 可迭代物件至少要有一個元素。 如果它只有一個元素,則元素直接返回 var result3 = arr4.reduce((value, element) => value * element);// 24 // 對每一個元素進行操作 arr2.forEach((item) { print(item); }); // expand, 以對每個元素呼叫f函式後生成的元素,按迭代的順序,返回新的Iterable var pairs = [[1, 2], [3, 4]]; var flattened = pairs.expand((pair) => pair).toList(); print(flattened); // => [1, 2, 3, 4]; var input = [1, 2, 3]; var duplicated = input.expand((i) => [i, i]).toList(); print(duplicated); // => [1, 1, 2, 2, 3, 3]
由於篇幅太長了, 剩下的一些資料型別下篇文章在繼續研究記錄吧