본문 바로가기
Languages/RUST

[RUST] TRPL : Chapter 8 - Collections

by odaebum 2024. 11. 29.
728x90

Chapter 8 - Collections

  • Collection의 데이터들은 힙에 저장된다.

1. Vector

→ 가변적인 개수의 값을 나란히 저장할 수 있다.

Vec <T> : 모든 값을 메모리에 나란히 배치하는 단일 데이터 구조에 여러 값을 저장할 수 있다.

  • 벡터는 제네릭을 사용하여 구현된다.
    let v: Vec<i32> = Vec::new();

vec! 메크로를 활용하여 지정한 값을 보관하는 새 벡터를 생성할 수 있다.

let v= vec![1, 2, 3];
  • update → .push();

  • get → &v[0] or .get(0)

    • .get() 메서드를 사용하면 벡터 사이즈보다 큰 값이 들어왔을 때 None을 반환한다.
  • 벡터의 메모리

          let mut v = vec![1, 2, 3, 4, 5];
    
          let first = &v[0]; //immutable
    
          v.push(6); //mutable
    
          println!("The first element is: {first}"); //immutable ==> error
    • 벡터 작동 방식 : 벡터는 메모리에서 값을 나란히 배치하기 때문에 벡터 끝에 새 요소를 추가하려면 새 메모리를 할당하고 벡터가 현재 저장된 곳에 모든 요소를 나란히 배치할 공간이 충분하지 않으면, 이전 요소를 새 공간에 복사해야 할 수 있다.
  • 벡터의 반복

          let mut v = vec![100, 32, 57];
          for i in &mut v {
              *i += 50; //역참조를 통해서 값 변경
          }
  • 벡터는 열거형을 통해서 여러 유형을 저장할 수 있다.

    —> 왜 구조체를 사용할 수 있다는 말은 나오지 않는 것인가.

    → 벡터는 제네릭으로 이루어져야 해서 그런가?

2. String

→ char 의 모음

  • 기본적으로 문자열 리터럴과 String은 다른것이다. 따라서 to_string() 을 사용하여 String을 생성할 수 있다.

          let data = "initial contents";
    
          let s = data.to_string();
    
          // the method also works on a literal directly:
          let s = "initial contents".to_string();
          let s = String::from("initial contents");
  • 문자열 추가 : - 소유권이 없다.

    1. .push_str();

    2. .push(); : 단일 문자 추가

    3. +

       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
    4. format!

       let s1 = String::from("tic");
       let s2 = String::from("tac");
       let s3 = String::from("toe");
      
       let s = format!("{s1}-{s2}-{s3}");
  • Rust는 문자열 인덱싱을 지원하지 않는다. 왜냐하면 Rust는 문자 각각이 2바이트이기 때문이다.

    • .chars() 를 사용한다.

      for c in "Зд".chars() {
        println!("{c}");
      }
      
      З
      д

3. Hash map

→ 특정 키와 값을 연관시킴.

    use std::collections::HashMap;

    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
  • 값 가져오기
    • Option<&V> 형태로 가져와 항목이 없으면 0으로 설정하여 None처리를 진행함.
    let team_name = String::from("Blue");
    let score = scores.get(&team_name).copied().unwrap_or(0);

해시 맵과 소유권

  • 해시 맵으로 이동이 되면 기존 변수를 사용할 수 없다.

해시 맵 업데이트

  1. 값 덮어쓰기
    use std::collections::HashMap;

    let mut scores = HashMap::new();

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

    println!("{scores:?}"); //25
  1. 키가 없는 경우에만 키와 값 추가
    use std::collections::HashMap;

    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);

    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50);

    println!("{scores:?}"); //{"Yellow": 50, "Blue": 10}
  1. 이전 값을 기반으로 값 업데이트
    use std::collections::HashMap;

    let text = "hello world wonderful world";

    let mut map = HashMap::new();

    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }

    println!("{map:?}"); //{"world": 2, "hello": 1, "wonderful": 1}
728x90