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

Rust 콜렉션과 문자열

집합(Collection)은 데이터 구조에서 가장 일반적인 데이터 저장 형식으로, Rust 표준 라이브러리는 개발자가 데이터 구조 작업을 처리하는 데 도움이 되는 다양한 집합 타입을 제공합니다。

벡터

벡터(Vector)는 여러 값을 저장하는 단일 데이터 구조이며, 이 구조는 동일한 타입의 값을 메모리에서 선형으로 저장합니다。

벡터는 선형 표본이며, Rust에서는 Vec<T>로 표현됩니다。

벡터의 사용 방식은 목록(List)과 유사합니다. 이렇게 특정 타입의 벡터를 생성할 수 있습니다:

let vector: Vec<i32>= Vec::new(); // 타입이 i32 의 비어 있는 벡터
let vector = vec![1i 2i 4i 8];     // 배열로 벡터 생성

우리는 자주 연속적인 작업을 사용하지만, 추가와 스택의 push 작업은 본질적으로 같습니다. 따라서 벡터는 단일 요소를 추가하는 push 메서드 만을 사용합니다:

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

실행 결과:

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

append 메서드는 하나의 벡터를 다른 벡터의 끝에 추가하는 데 사용됩니다:

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

실행 결과:

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

get 메서드는 벡터에서 값을 꺼내는 데 사용됩니다:

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

실행 결과:

1

벡터의 길이를 논리적으로 추론할 수 없기 때문에, get 메서드는 항상 값을 가져올 수 없는 것을 보장할 수 없으며, 따라서 get 메서드의 반환 값은 Option 열거형이며, 비어 있을 수 있습니다。

이는 안전한 값을 가져오는 방법이지만, 쓰기가 좀 복잡합니다. 값의 인덱스가 벡터 인덱스 범위를 벗어나지 않을 것이라면, 배열 값 문법을 사용할 수도 있습니다:

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

실행 결과:

2

하지만 우리가 v[4let v = vec![

for i in &v {

fn main() {
    println!("{}", i);10for i in &mut v { 32i 57];
    조회 과정에서 변수의 값을 변경해야 할 경우:
            let mut v = vec![
    }
}

실행 결과:

100
32
57

0,

fn main() {
    ,10for i in &mut v { 32i 57];
    =
        *0; +문자열 5String 클래스(String)은 이까지 많이 사용되었으므로 많은 메서드가 독자에게 잘 알려져 있습니다. 이 장에서는 문자열 메서드와 UTF를 주로 소개합니다.
    }
}

속성。

새 문자열:-8 let string = String::new();

기본 타입을 문자열로 변환:

let one =

정수를 문자열로

let float = 1let slice = "slice".to_string();         // .
.to_string(); 1부동소수점 수를 문자열로3let slice = "slice".to_string();     // 문자열 슬라이싱을 문자열로
UTF를 포함 // 문자의 문자열:

let hello = String::from("السلام عليكم");-8 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('!'); // 추가할 문자
사용하여       // 문자열 연결:

String::from("Hello, "); + =

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

=

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
이 문법은 문자열 슬라이싱을 포함할 수도 있습니다:1 + "-" + &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);
}

실행 결과:

thread 'main'에서 'byte index'에서 패닉했습니다 3 은 문자 경계가 아닙니다; '中' 내부에 있습니다 (바이트) 2..5) of `EN中文`', src\libcore\str\mod.rs:2069:5 
주의: `RUST_BACKTRACE=`와 함께 실행하세요1환경 변수를 통해 백트레이스를 표시하려면 ` environment variable to display a backtrace.

지도표

지도표(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의 자동 타입 추론 기계 때문입니다.

실행 결과:

red

insert 메서드와 get 메서드는 매핑 테이블에서 가장 많이 사용되는 두 가지 메서드입니다.

매핑 테이블은 이터레이터를 지원합니다:

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";
    }
}