#list #array #vec #wrapper #utils #interior-mutability #api-bindings

arraylist

基于Rust向量实现构建的rust包装器。类似于Java Arraylist,使用起来像Python列表和JavaScript数组一样直观。

3个版本

0.1.5 2021年6月30日
0.1.4 2021年6月30日
0.1.3 2021年6月27日
0.1.2 2021年6月27日
0.1.0 2021年6月26日

#2066数据结构

每月26次下载
simple_getopt 中使用

MIT 许可证

2MB
438 代码行

包含 (rust库,82KB) target/release/libarraylist.rlib,(rust库,82KB) libarraylist-27ddee64e3a271ff.rlib

arraylist

名称

arraylist -- 在Rust向量实现之上构建的直观的Rust向量包装器。类似于Java Arraylist,也可以像Python列表函数和JavaScript数组一样使用。

安装

在 Cargo.toml 文件中

[dependancies]
arraylist = {git = "https://github.com/2teez/arraylist"}

OR

[dependancies]
arraylist = "0.1.3"

在 main.rs 文件中

使用方法

#[macro_use]
extern crate arraylist;

use arraylist::arl::ArrayList;

描述

arraylist - 是基于Rust标准向量实现构建的rust包装器。它使得使用向量作为列表或在其他语言(如Java、JavaScript等)中的可增长数组时更加直观,无需与Rust借用检查器“战斗”;这是在Rust中编码时始终存在的、固执但伟大的朋友。

arraylist 不是在Rust中重写的 vec,而是一个包装器,它提供了安全、更简单且可能的接口,同时使用了Rust语言提供的“内部可变性”。

使用 crate arraylist 可以使您能够处理不可变值、对象等,同时无需在代码的每个地方都使用“mut”关键字,即可进行多次更改。尽管如此,您可能仍然需要在某些情况下使用它。但您大部分时间都在处理不可变值。

arraylist crate 提供的函数与 Java ArrayList 方法非常相似。即使您以前没有使用过 Java,它也会感觉直观,并隐藏了 rust-lang 中的一些“头疼”的工作。

示例

以下代码仅使用 rust 中的 vec 无法实现

let vec = vec![1, 2, 3, 4, 5];
vec.push(6); // cannot borrow as mutable

使用 arraylist,可以这样工作,使用不可变变量

let arr = arraylist![1, 2, 3, 4];
arr.push(5);
arr.push(6);

// print out your arraylist like so:
arr.print(); // [1, 2, 3, 4, 5, 6]

然而,要在 vec 中获得相同的结果,您必须使变量可变。

您也可以使用 arraylist 如此使用可变变量

let mut arr = arraylist![];
arr.add(1).add(2).add(3).add(4).add(5).finish();

arr.print(); // [1, 2, 3, 4, 5]
// or use
println!("{}", arr); // same result as above

请注意,在可变对象 'object' 上调用函数 finish 时,您将获得一个不可变对象。您可以将它们全部链接起来,得到一个不可变的变量。

// you can create, add, and assign or print it all out
// like so

ArrayList::new()
         .add("lagos")
         .add("enugu")
         .add("cairo")
         .finish()
         .print();  // ["lagos", "enugu", "cairo"]
// or assign
let places = ArrayList::new().ad(..)..finish();
places.print();

尝试在 Rust 中使用原生的 vec 来实现这个功能

let al = arraylist![].add("bruno").add("b").add("🦀")
     .add("ß").add("བོད་སྐད་ལ").finish();

 // a for_each macro, takes an immutable variable and a closure
 // each of the string in the arraylist becomes a titled case
 for_each!(al, |a| {
     let mut upper = a.chars().collect::<Vec<_>>();
     upper[0] = upper[0].to_ascii_uppercase();
     upper.iter().fold(String::from(""), |mut a, b| {
         a.push(*b);
         a
     })
 })
 .print();  // ["Bruno", "B", "🦀", "ß", "བ\u{f7c}ད་ས\u{f90}ད་ལ"]

ArrayList 方法

arraylist 使用了 Java、JavaScript、Python 等语言中常用的函数/方法名称。因此,下面展示的方法易于使用。我打算展示并演示每个方法的使用方式。但请注意,每个程序员的表达都受其知识量的限制。

以下是在 ArrayList 模块中可用的方法列表

  1. add

    pub fn add(&mut self) -> &ArrayList<T>

    • 将一个值推入可变实例的空或非空 ArrayList 中。列表的长度增加 1。
       let al = ArrayList::new()
                   .add("Lagos")
                   .add("Abuja")
                   .finish();
    
  2. add_all

    pub fn add_all(&self, collection: &[T])

    • 接受一个切片引用,并将切片中的每个元素追加到列表末尾。使用底层 vec 的扩展函数。列表的长度增加切片中元素的数量。列表的容量也相应调整。
    let al = arraylist![1, 2];
        al.add_all(&[3, 4, 5]);
        al.print(); // [1, 2, 3, 4, 5]
    
  3. add_all_at_index

    pub fn add_all_at_index(&self, idx: usize, collection: &[T])

    • 此函数接受两个参数;要插入的集合的起始索引。以及要插入的切片引用。它在从切片参数中添加值时将列表中的值向右移动。注意,起始索引 必须 不大于列表本身的长度。如果起始索引大于列表的长度或大小,您的代码将崩溃。
    let al = arraylist![1, 2, 3];
    al.add_all_at_index(1, &[4, 5, 6]);
    al.print(); // [1, 4, 5, 6, 2, 3]
    
  4. cap

    pub fn cap(&self) -> usize

    • 返回列表的容量。
       println!(
           "{}",
           ArrayList::start_with(&["coke", "fanta", "pepsi", "chapman"]).cap()
        );
    
  5. clear

    pub fn clear(&self)

    • 清除:从列表中移除所有元素。
        let al = arraylist![1, 2, 3];
        al.clear();
        al.print(); // []
    
  6. clone

    pub fn clone(&self) -> ArrayList<T>

    • 返回一个新的 ArrayList 实例,具有相同的元素。它不是一个引用。通过 clone 方法对元素进行的更改 不会 以任何方式影响其他实例。
        let new_clone = al.clone();
        new_clone.push(1);
        new_clone.push(3);
        new_clone.print(); // [1, 3]
        al.print(); // []
    
  7. contains

    pub fn contains(&self, value: T) -> bool

    • 如果列表包含参数的值,则返回 true。
        let players = arraylist!["Yekini", "Pele", "Ronaldo", "Messi"];
        println!("{}", players.contains("Yakubu")); // false
        println!("{}", players.contains("Ronaldo")); // true
    
  8. copy

    pub fn copy(&self) -> &ArrayList<T>

    • 返回一个 ArrayList 实例的引用 "副本"。对其中一个所做的任何更改都会反映在另一个上。这与 clone 方法不同。注意,您可以对该实例进行多次复制。
            let new_copy = al.copy();
            new_copy.push(1);
            new_copy.push(3);
            al.push(0);
            new_copy.print(); // [1, 3, 0]
            al.print(); // [1, 3, 0]
    
  9. default

    pub fn default(&self) -> ArrayList<T>

    • 实现 ArrayList 的 Default 特性。返回一个具有每个元素默认值的新的 ArrayList 实例。
           #[derive(Debug, Clone, PartialEq)]
           struct Person<'a> {
               name: &'a str,
               age: u32,
           }
           let array = ArrayList::<Person>::default();
           array.print(); //   []
           array.push(Person {
               name: "boris",
               age: 23,
           });
           array.print(); //  [Person { name: "boris", age: 23 }
    
  10. ensure_capacity

    pub fn ensure_capacity(size: usize) -> ArrayList<T>

    • 构造一个新的空 ArrayList,具有指定的容量。
        let na: ArrayList<u8> = ArrayList::ensure_capacity(10);
        println!("{}", na.cap()); // 10
    
  11. finish

    pub fn finish(&self) -> ArrayList<T>

    • 返回一个不可变的 arraylist。通常在调用 add 函数后调用,该函数创建一个可变列表并将值推入列表。 finish 是调用以获得所需不可变变量的函数。
        let al = arraylist![]
                .add("Lagos")
                .add("Abuja")
                .finish();  // immutable
            al.print();     // ["Lagos", "Abuja"]
    
  12. for_each

    pub fn for_each(&self, f: fn(T))

    • 它接受一个闭包,并在列表中的每个元素上执行闭包中的操作。但它不会更改列表的元素。
        // square all odd numbers
        let nums = arraylist!(1, 2, 3, 4, 5);
        nums.for_each(|a| {
            println!(
                "{}",
                match a % 2 != 0 {
                    true => a * a,
                    false => a,
                }
            )
        });
        nums.print(); // [1, 2, 3, 4, 5]
        // if you want nums to change use macro `for_each!` instead
    
  13. from_slice

    pub fn from_slice(collection: &[T]) -> ArrayList<T>

    • 接受一个值切片的引用,并返回具有相同值的 ArrayList。
        let fruits = ArrayList::from_slice(&["pineapple", "pear", "banana", "orange"]);
        fruits.print(); //  ["pineapple", "pear", "banana", "orange"]
    
  14. get

    pub fn get(&self, index: usize) -> Option<T>

    • get 需要要获取值的索引。它返回一个包裹在 option 变体中的指定位置的值。如果索引大于列表的长度,操作将引发恐慌。否则,它返回该索引处的值。
        let fruits = ArrayList::from_slice(&["pineapple", "pear", "banana", "orange"]);
        // println!("{}", fruits.get(31).unwrap()); // panics
        println!("{}", fruits.get(3).unwrap()); // orange
    
  15. index_in

    pub fn index_in(&self, value: usize) -> Option<T>

    get 方法类似。

  16. index_of

    pub fn index_of(&self, value: T) -> Option<usize>

    • 接收一个参数,即要查找的值,并返回该值在列表中的索引。与 index_of 相似,它是 getindex_in 的反转。如果值不在列表中,则解包操作将引发恐慌。
        //println!("{:?}", fruits.index_of("pine").unwrap()); // panics
        println!("{:?}", fruits.index_of("orange").unwrap()); // 3
    
  17. index_of_all

    pub fn index_of_all(&self, value: T) -> Vec<usize>

    • 接收一个参数,即要查找的值,并返回一个包含所有可能找到该值的索引的 usize 向量。
        println!(
                "{:?}",
                "hello, world is luck to be loud"
                    .chars()
                    .collect::<ArrayList<_>>()
                    .index_of_all('l')
        ); // [2, 3, 10, 16, 27]
    
  18. insert

    pub fn insert(&self, index: usize, value: T)

    • 给定两个参数;要插入的值的索引和要插入的值。此函数将索引(或位置)指定的值移动,并“插入”新的值。如果索引大于列表长度,将引发恐慌。
            let places = arraylist![].add("Lagos").add("Abuja").finish();
            places.print();  // ["Lagos", "Abuja"]
            places.insert(1, "kumasi");
            places.print();  // ["Lagos", "kumasi", "Abuja"]
    
  19. is_empty

    pub fn is_empty(&self) -> bool

    如果此列表不包含任何元素,则返回 true,否则返回 false。

        let al = arraylist!["yah", "yak", "kah"];
        al.clear();
        println!("{}", al.is_empty()); // true
        println!("{}", arraylist![3, 5, 7, 9].is_empty()); // false
    
  20. len

    pub fn len(&self) -> usize

    • 返回列表的长度。
        let al = arraylist!["yah", "yak", "kah"];
        println!("{}", al.len()); // 3
        al.clear();
        println!("{}", al.len()); // 0
    
  21. new

    pub fn new() -> ArrayList<T>

    • 使用列表类型的默认值构建一个新实例的 arraylist。
        let al = ArrayList::<String>::new();
        // or
        let al: ArrayList<String> = ArrayList::new();
    
  22. pop

    pub fn pop(&self) -> Option

    • 移除并返回列表中的最后一个元素。减少列表的长度和大小。列表的容量不受影响。
            let fruits = arraylist![
                "orange",
                "pear",
                "pineapple",
                "tangerine",
                "apple",
                "strawberry"
            ];
            println!("{}", fruits.pop().unwrap());
            println!("{}", fruits.pop().unwrap());
            fruits.print(); // ["orange", "pear", "pineapple", "tangerine"]
    
  23. print

    pub fn print(&self)

    • 打印出列表中的元素。调用 print 比使用 rust 中提供的宏 println! 更直观。
                let fruits = arraylist![
                    "orange",
                    "pear",
                    "pineapple",
                    "tangerine",
                    "apple",
                    "strawberry"
                ];
    
                fruits.print(); //["orange", "pear", "pineapple", "tangerine", "apple", "strawberry"]
    
  24. push

    pub fn push(&self, value: T) -> bool

    • 将指定元素追加到此列表的末尾。但与 add 不同,它不会使列表可变来完成此操作。尽管它类似于 add,但它不能像方法 add 那样用于“构建器”设计方式。返回一个布尔值。
                let al: ArrayList<i32> = ArrayList::new();
                al.push(-34);
                al.push(39);
                al.push(25);
    
                al.print(); // [-34, 39, 25]
    
  25. push_on_index

    pub fn push_on_index(&self, index: usize, value: T)

    • 接收两个参数;要插入的索引和要插入的值。它的工作方式与 insert 方法完全相同。
                let al = arraylist![1, 2, 3];
                al.push_on_index(1, 7);
                al.push_on_index(0, 9);
                al.print(); // [9, 1, 7, 2, 3]
    
  26. remove

    pub fn remove(&self, index: usize) -> T

    • 它移除并返回由提供的索引参数指定的列表中的元素。它也减少了列表的长度。如果索引大于列表长度,将引发恐慌。
            println!("{}", al.remove(al.len() - 1)); // 3
            al.print();  // [9, 1, 7, 2]
            println!("{}", al.remove(2)); // 7
            al.print();  // [9, 1, 2]
    
  27. remove_if

    pub fn remove_if(&self, f: fn(T) -> bool)

    • 它类似于 remove,但它不是使用索引,而是接收一个闭包作为参数,并将该闭包应用于列表的每个元素。
            let al = arraylist![1, 2, 3, 4, 5, 6, 7, 8, 9];
                al.print(); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
                al.remove_if(|a| a % 2 == 0);
                al.print(); // [1, 3, 5, 7, 9]
    
  28. replace

    pub fn replace(&self, index: usize, value: T)

    • 它用提供的索引指定的新值替换指定的元素。如果索引大于列表长度,将引发恐慌。
            al.replace(0, 23);
            al.print();  // [23, 3, 5, 7, 9]
    
  29. size

    pub fn size(&self) -> usize

    • 返回列表中元素的数量。类似于方法 len
            println!("{}", al.len()); // 5
    
  30. start_with

    pub fn start_with(collection: &[T]) -> ArrayList<T>

    • 使用从参数提供的切片引用构建并返回一个 Arraylist ArrayList<T>,arraylist 的类型由提供的切片的类型推断得出。类型也可以指定。
            let nums = ArrayList::start_with(&[1, 2, 3, 4, 5, 6]);
                nums.print(); // [1, 2, 3, 4, 5, 6]
    
  31. sub_list

    pub fn sub_list(&self, start: usize, stop: usize) -> Option<ArrayList>

    • 从列表中返回所有索引在起始索引(包含)和结束索引(不包含)之间的元素。如果结束索引大于列表长度,则引发恐慌。
            let nums = ArrayList::start_with(&[1, 2, 3, 4, 5, 6]);
                nums.print(); // [1, 2, 3, 4, 5, 6]
                nums.sub_list(1, 4).unwrap().print(); // [2, 3, 4]
    
  32. to_vec

    pub fn to_vec(&self) -> Vec

    • 将列表的元素转换为并返回一个向量。这实际上非常棒,因为 Rust 的 vec 有很多方法,而这个包装器没有实现。将 arraylist 转换为 vec 使得可以使用向量中的许多方法。

待办事项

[] 执行更多复杂场景的测试和基准测试。

无运行时依赖