[Aptos學習筆記#7]Move進階使用 - 使用Vector管理集合 - Managing Collections with Vector
IPFS
      目錄
- 為什麼需要Vector?
 - Vector是什麼?
 - 內聯 Vector 定義的十六進制數組與字符 - Hex and Bytestring literal for inline vector definitions
 - Vector 速查表 - Vector Cheatsheet
 
一. 為什麼需要Vector?
前面的筆記中我們已經很熟悉結構體的類型了,它讓我們可以創建自己的類型並儲存複雜的數據,但有時候我們需要更動態、可擴展性核可管理性的功能,這邊Move提供了向量Vector的概念來處理
二. Vector是什麼?
- 用於儲存數據集合的內置類型( build-in type)
 - 集合數據能夠是任何類型(但僅一種)
 - Vector的功能實際上是由Move VM提供的
 - 使用Vector唯一的辦法就是使用Move標準庫和native函數
 
script {
    use 0x1::Vector;
    fun main() {
        // 使用泛型創建一個空的 Vector
        let a = Vector::empty<u8>();
        let i = 0;
        // 將值塞入剛剛創建的Vector中
        while (i < 10) {
            Vector::push_back(&mut a, i);
            i = i + 1;
        };
        // 現在印出Vector的長度
        let a_len = Vector::length(&a);
        0x1::Debug::print<u64>(&a_len);
        // 移除掉兩個元素
        Vector::pop_back(&mut a);
        Vector::pop_back(&mut a);
        // 再次印出Vector長度
        let a_len = Vector::length(&a);
        0x1::Debug::print<u64>(&a_len);
    }
}
Vector最多可以儲存U64個單個非引用類型(single non-reference type)的值
例子: 為了理解Vector如何幫助管理巨大的存儲量,這邊撰寫一個模塊 ( Module )
module Shelf {
    use 0x1::Vector;
    struct Box<T> {
        value: T
    }
    struct Shelf<T> {
        boxes: vector<Box<T>>
    }
    public fun create_box<T>(value: T): Box<T> {
        Box { value }
    }
    // 對於不可複製的內容本方法不可行
    public fun value<T: copy>(box: &Box<T>): T {
        *&box.value
    }
    public fun create<T>(): Shelf<T> {
        Shelf {
            boxes: Vector::empty<Box<T>>()
        }
    }
    // 將Box的值移入Vector
    public fun put<T>(shelf: &mut Shelf<T>, box: Box<T>) {
        Vector::push_back<Box<T>>(&mut shelf.boxes, box);
    }
    
    // 將Vector中的元素移出
    public fun remove<T>(shelf: &mut Shelf<T>): Box<T> {
        Vector::pop_back<Box<T>>(&mut shelf.boxes)
    }
    // 計算Vector的長度
    public fun size<T>(shelf: &Shelf<T>): u64 {
        Vector::length<Box<T>>(&shelf.boxes)
    }
}
在Script中,我們首先創建一個 Shelf,並為其提供幾個 Box,並觀察如何在Module中使用 Vector
script {
    use {{sender}}::Shelf;
    fun main() {
        // 創建一個shelf和兩個u64類型的Box
        let shelf = Shelf::create<u64>();
        let box_1 = Shelf::create_box<u64>(99);
        let box_2 = Shelf::create_box<u64>(999);
        // 將剛剛創建的兩個Box推進Vector
        Shelf::put(&mut shelf, box_1);
        Shelf::put(&mut shelf, box_2);
        // 印出長度 - 結果為2
        0x1::Debug::print<u64>(&Shelf::size<u64>(&shelf));
        // 拿走最後一個推進Vector的Box
        let take_back = Shelf::remove(&mut shelf);
        let value     = Shelf::value<u64>(&take_back);
        // 驗證我們拿出來的Box值是999
        assert(value == 999, 1);
        // 再次印出Vector長度 - 結果為1
        0x1::Debug::print<u64>(&Shelf::size<u64>(&shelf));
    }
}
Vector非常強大,它允許我們存儲大量數據(最大長度為 18,446,744,073,709,551,615),並讓我們在索引的存儲中使用它
三. 內聯 Vector 定義的十六進制數組與字符 - Hex and Bytestring literal for inline vector definitions
Vector也代表著表示字符串
VM 支援將vector<u8>當作參數傳遞給腳本中的主函數的方式
例子: 我們也可以在使用十六進制文本在Script或Module中定義一個vector<u8>
script {
    use 0x1::Vector;
    // 這是在main中傳入參數的方式
    fun main(name: vector<u8>) {
        let _ = name;
        // 這是我們使用文字的方式
        // 這邊表示的是一個hello world的字符串
        let str = x"68656c6c6f20776f726c64";
        // 十六進制的文字也傳給我們vector<u8>
        Vector::length<u8>(&str);
    }
}
有個簡單的方式就是使用字節串文字(bytestring literals)
script {
    fun main() {
        // 使用b"<我們想輸入的字符串>"的方式更簡易
        let _ = b"hello world";
    }
}
它們被當成是ASCII 字符串,也被表示為vector<u8>
四. Vector 速查表 - Vector Cheatsheet
在標準庫中的簡短Vector方法速查表
1.創建一個類型為<E>的空Vector
Vector::empty<E>(): vector<E>;
2.取得Vector長度
Vector::length<E>(v: &vector<E>): u64;
3.將元素推向Vector的末端
Vector::push_back<E>(v: &mut vector<E>, e: E);
4.獲取對Vector的可變引用,不可變引用可以使用Vector::borrow()
Vector::borrow_mut<E>(v: &mut vector<E>, i: u64): &E;
5.從Vector末端取走一個元素
Vector::pop_back<E>(v: &mut vector<E>): E;
標準庫中的Vector模塊:
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!





- 来自作者
 - 相关推荐