Общие коллекции

Эта тема требует отдельного изучения и как факт я намереваюсь сделать перевод reference и стандартной библиотеки rust

Это в общей коллекции представлено как доступные коллекции

  • Sequences: Vec, VecDeque, LinkedList
  • Maps: HashMap, BTreeMap
  • Sets: HashSet, BTreeSet
  • Misc: BinaryHeap

Вектор

Векторы позволяют хранить более одного значения в единой структуре данных, хранящей элементы в памяти один за другим. Векторы могут хранить данные только одного типа.

fn main() {
    let v: Vec<i32> = Vec::new();
}

//или

fn main() {
    let v = vec![1, 2, 3]; //это через макрос с инициализацией значений
}

Векторы можно push

#![allow(unused)]
fn main() {
    let mut v = Vec::new();

    v.push(5);
    v.push(6);
    v.push(7);
    v.push(8);

}

Чтение векторов

#![allow(unused)]
fn main() {
    let v = vec![1, 2, 3, 4, 5];

    let third: &i32 = &v[2];
    println!("The third element is {third}");

    let third: Option<&i32> = v.get(2);
    match third {
        Some(third) => println!("The third element is {third}"),
        None => println!("There is no third element."),
    }
}

Перебор значений в вектора

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

Хранение в векторах своих типов Enum

#![allow(unused)]
fn main() {
    enum SpreadsheetCell {
        Int(i32),
        Float(f64),
        Text(String),
    }

    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
}

Хранение закодированного текста UTF-8 в строках

Строки String

В Rust есть только один строковый тип в ядре языка - срез строки str, обычно используемый в заимствованном виде как &str.

String фактически реализован как обёртка вокруг вектора байтов с некоторыми дополнительными гарантиями, ограничениями и возможностями

#![allow(unused)]
fn main() {
let mut s = String::new();
}

to_string преобразует все к типажу Display

#![allow(unused)]
fn main() {
let data = "initial contents";

    let s = data.to_string();

    // The method also works on a literal directly:
    let s = "initial contents".to_string();
}

push_str добавляет строку

  • переменная должна быть mut
  • добавляет в конец строки строку
#![allow(unused)]
fn main() {
let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
println!("s2 is {s2}");
}

push добавляет в конец строки символ

#![allow(unused)]
fn main() {
    let mut s = String::from("lo");
    s.push('l');
}

+ и макрос format!

#![allow(unused)]
fn main() {
    let s1 = String::from("Hello, ");
    let s2 = String::from("world!");
    let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
}

Работает по принципу макроса println!

#![allow(unused)]
fn main() {
    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");

    let s = format!("{s1}-{s2}-{s3}");

}

Получение символов по индексу

существует три способа рассмотрения строк с точки зрения Rust: как байты, как скалярные значения и как кластеры графем

#![allow(unused)]
fn main() {
let hello = "Здравствуйте";

let s = &hello[0..4];
}

выведет 4 байта или 2 буквы

  • Для перебора букв использовать метод chars
  • Для перебора байт использовать метод bytes
#![allow(unused)]
fn main() {
for c in "Зд".chars() {
    println!("{c}");
}
З
д

for b in "Зд".bytes() {
    println!("{b}");
}
208
151
208
180

}

HashMap

Тип HashMap<K, V> хранит ключи типа K на значения типа V. Данная структура организует и хранит данные с помощью функции хеширования.

Создание новой хеш-карты

#![allow(unused)]
fn main() {
    use std::collections::HashMap;

    let mut scores = HashMap::new(); //создание новой карты

    scores.insert(String::from("Blue"), 10); //добавить элемент в карту
    scores.insert(String::from("Yellow"), 50);

}

Доступ к hash по get

#![allow(unused)]
fn main() {
    let team_name = String::from("Blue");
    let score = scores.get(&team_name).copied().unwrap_or(0);
}

перебор карт

#![allow(unused)]
fn main() {
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    for (key, value) in &scores {
        println!("{key}: {value}");
    }

}

Хэш карты забирают владение на себя. Нужно это учитывать.

Перезапись старых значений

#![allow(unused)]
fn main() {
    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 25);

    println!("{scores:?}");

}

просто перезапишет новое значение. Новое значение будет вставлено, если нет такого ключа.

Добавить только новые значения и не перезаписывать старые

#![allow(unused)]
fn main() {
    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);

}

метод entry позволяет добавить только не существующие значения вместе с or_insert

Считает количество повторений

#![allow(unused)]
fn main() {
    use std::collections::HashMap;

    let text = "hello world wonderful world";

    let mut map = HashMap::new(); //создали hash

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0); // добавим новый если нет и присвоим 0
        *count += 1; //разыменовали ссылку на ключ и увеличили на 1
    }

    println!("{map:?}");


}

Хэширование

Hasher - это тип, реализующий трейт BuildHasher.

функция хеширования SipHash, может противостоять атакам класса: отказ в обслуживании, Denial of Service (DoS) с использованием хеш-таблиц siphash.