English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

المجموعات والكلمات Rust

集合(集合)是数据结构中最普遍的数据存放形式,Rust(鲁斯特) 标准库中提供了丰富的集合类型帮助开发者处理数据结构的操作。

向量(向量)

向量(向量)是一个存放多值的单数据结构,该结构将相同类型的值线性的存放在内存中。

向量(向量)是线性表,在 Rust(鲁斯特) 中的表示是 Vec<T>。

向量(向量)的使用方式类似于列表(List),我们可以通过这种方式创建指定类型的向量:

let vector: Vec<i32> = Vec::new(); // 创建类型为 i32 的空向量
let vector = vec![1, 2, 4, 8]; // 通过数组创建向量

نستخدم عمليات إضافة النسق بشكل متكرر، ولكن عملية الإضافة مشابهة لعملية push في الدفعة، لذا يتم استخدام طريقة push فقط في التجميع لدمج عنصر واحد:

fn main() {
    let mut vector = vec![1, 2, 4, 8];
    vector.push(16);
    vector.push(32);
    vector.push(64);
    println!("{:?}", vector);
{}

نتيجة التنفيذ:

[1, 2, 4, 8, 16, 32, 64]

يستخدم append لدمج مجموعة واحدة في نهاية مجموعة أخرى:

fn main() {
    let mut v1: Vec<i32> = vec![1, 2, 4, 8];
    let mut v2: Vec<i32> = vec![16, 32, 64];
    v1.append(&mut v2);
    println!("{:?}", v1);
{}

نتيجة التنفيذ:

[1, 2, 4, 8, 16, 32, 64]

يستخدم get لاستخراج القيمة من التجميع:

fn main() {
    let mut v = vec![1, 2, 4, 8];
    println!("{}", match v.get(0) {
        Some(value) => value.to_string(),
        None => "None".to_string(),
    });
{}

نتيجة التنفيذ:

1

بسبب أن طول التجميع لا يمكن استنباطه منطقيًا، لا يمكن التأكد من أن طريقة get ستحصل على القيمة، لذا يكون العودة لطريقة get هي فئة Option، وهي قد تكون فارغة.

هذه هي طريقة آمنة للحصول على القيمة، ولكن الكتابة تبدو معقدة. إذا كنت تستطيع التأكد من أن قيمة المؤشر لن تتجاوز نطاق مؤشر المجموعة، يمكنك أيضًا استخدام جملة التعبير عن التجميع:

fn main() {
    let v = vec![1, 2, 4, 8];
    println!("{}", v[1]);
{}

نتيجة التنفيذ:

2

لكن إذا حاولنا الحصول على v[4]، فإن المجموعة ستعود بخطأ.

تمرير المجموعة:

fn main() {
    let v = vec![100, 32, 57];
    for i in &v {
            println!("{}", i);
    {}
{}

نتيجة التنفيذ:

100
32
57

إذا كنت بحاجة إلى تغيير قيمة المتغير أثناء التمرير:

fn main() {
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;
    {}
{}

الخطوط النصية

الخطوط النصية (String) تم استخدامها بشكل كبير حتى الآن، لذا أصبحت العديد من الطرق معروفة للقراء. يهدف هذا الفصل إلى شرح طرق الخطوط النصية وأصناف UTF-8.

إنشاء نص جديد:

let string = String::new();

تحويل الأنواع الأساسية إلى نصوص:

let one = 1.to_string();                    // عدد صحيح إلى نص
let float = 1.3.to_string();                // عدد عشري إلى نص
let slice = "slice".to_string();            // قطعة نصية إلى نص

النصوص التي تحتوي على أحرف UTF-8:

let hello = String::from("السلام عليكم");
let hello = String::from("Dobrý den");
let hello = String::from("Hello");
let hello = String::from("שָׁלוֹם");
let hello = String::from("नमस्ते");
let hello = String::from("こんにちは");
let hello = String::from("안녕하세요");
let hello = String::from("你好");
let hello = String::from("Olá");
let hello = String::from("Здравствуйте");
let hello = String::from("Hola");

إضافة النصوص للسلسلة:

let mut s = String::from("run");
s.push_str("oob");                      // إضافة قطعة نصية
s.push('!');                            // إضافة حرف

استخدام علامة التبديل + للجمع بين النصوص:

let s1 = String::from("Hello,");
let s2 = String::from("world!");
let s3 = s1 + &s2;

هذه الجملة يمكن أن تحتوي أيضًا على قطع النصوص:

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;

استخدام ماكرو format!:

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);

طول النص:

let s = "hello";
let len = s.len();

قيمة len هنا هي 5.

let s = "你好";
let len = s.len();

قيمة len هنا هي 6. لأن اللغة الصينية معتمدة على رمز UTF-8، وكل حرف طول 3 بايت، لذا الطول هو 6. ولكن يدعم Rust كائنات الأحرف UTF-8، لذا يمكنك حساب عدد الأحرف أولاً بتحويل النص إلى مجموعة أحرف:

let s = "hello你好";
let len = s.chars().count();

قيمة len هنا هي 7، لأن هناك 7 حروف. سرعة حساب الأحرف أبطأ بكثير من سرعة حساب الطول.

تدوير النص:

fn main() {
    let s = String::from("hello中文");
    for c in s.chars() {
        println!("{}", c);
    {}
{}

نتيجة التنفيذ:

h
e
l
l
o
中
文

استخراج حرف من النص:

fn main() {
    let s = String::from("EN中文");
    let a = s.chars().nth(2);
    println!("{:?}", a);
{}

نتيجة التنفيذ:

Some('中')

ملاحظةالوظيفة nth هي طريقة لسحب قيمة من مولد، لا تستخدم هذا الطريقة أثناء التدوير! لأن طول كل حرف UTF-8 قد يختلف!

إذا كنت ترغب في قطع جزء من النص:

fn main() {
    let s = String::from("EN中文");
    let sub = &s[0..2];
    println!("{}", sub);
{}

نتيجة التنفيذ:

EN

لكن يرجى ملاحظة أن استخدامه قد يؤدي إلى تقسيم حرف UTF-8! ذلك سيؤدي إلى خطأ:

fn main() {
    let s = String::from("EN中文");
    let sub = &s[0..3];
    println!("{}", sub);
{}

نتيجة التنفيذ:

النواة 'main' انفجرت عند 'byte index 3 is not a char boundary; it is inside '中' (bytes 2..5) of `EN中文`', src\libcore\str\mod.rs:2069:5 
ملاحظة: قم بتشغيل `RUST_BACKTRACE=1` كمتغير بيئي لعرض سلسلة التتبع.

الخريطة

الخريطة (Map) موجودة في العديد من اللغات. أكثرها شيوعًا هو خريطة الترميز المضغوط (Hash Map).

إنشاء جدول قيم المضغوط الجديد:

use std::collections::HashMap;
fn main() {
    let mut map = HashMap::new();
    map.insert("color", "red");
    map.insert("size", "10 m^2");
    println!("{}", map.get("color").unwrap());
{}

ملاحظةلا يتم تعريف نوع المفتاح بشكل مباشر في هيكل البيانات المضغوط، لأنه يتم تحديد النوع تلقائيًا بواسطة ميكانيكية Rust.

نتيجة التنفيذ:

أحمر

طريقة insert و طريقة get هي من أكثر الطرق استخدماً في جدول.

يدعم جدول Rust الم迭代.

use std::collections::HashMap;
fn main() {
    let mut map = HashMap::new();
    map.insert("color", "red");
    map.insert("size", "10 m^2");
    for p in map.iter() {
        println!("{:?}", p);
    {}
{}

نتيجة التنفيذ:

("color", "red") 
("size", "10 m^2")

التحليلات هي أزواج تمثل المفاتيح والمقادير.

يعد جدول Rust بنية بيانات مريحة، عندما تستخدم طريقة insert لضيف كائن جديد، إذا كان هناك مفتاح موجود بالفعل، فإنه سيقوم بتبديل القيمة الموجودة.

map.entry("color").or_insert("red");

معنى هذا الجملة هو إذا لم يكن هناك أي قيمة مرتبطة بكلمة "color"، فأضفها وضع القيمة على "red"، وإلا فتخطي.

إذا كنت قد确定了某个键,并想直接修改对应的值,有更快的方法:

use std::collections::HashMap;
fn main() {
    let mut map = HashMap::new();
    map.insert(1, "a");
    
    if let Some(x) = map.get_mut(&1) {
        *x = "b";
    {}
{}