반응형

■ 해쉬맵

HashMap은 키(key) 와 값(value)가 쌍으로 하는 데이터 구조를 갖고 있으며, 키와 값은 각각 동일한 타입으로 설정해야 한다. HashMap은 키를 이용하여 값을 조회할 수 있습니다.


◆ 해쉬맵 생성

해쉬맵을 생성하는 방법은 두가지입니다.

 

첫번째, HashMap 구조체의 new 함수를 활용한 생성

fn main(){
    use std::collections::HashMap;

    // HashMap 생성
    let mut hash_ages : HashMap<String, u32> = HashMap::new();
    // 데이터 삽입
    hash_ages.insert(String::from("Hyunmin Han"), 29);
    
    println!("HashMap : {:?}", hash_ages);
}

▶ 출력 결과

HashMap : {"Hyunmin Han": 29}

두번째, collect 메소드를 활용한 생성, iter 함수 앞 벡터가 HashMap의 키가 되고, zip 함수의 파라미터가 HashMap의 값이 됩니다.

fn main(){
    use std::collections::HashMap;
    // HashMap의 키에 해당하는 벡터 생성
    let names  = vec![String::from("Hyunmin Han"), String::from("Donghun Lee")];
    // HashMap의 값에 해당하는 벡터 생성
    let ages = vec![10, 50];
    // HashMap 생성
    let hash_ages: HashMap<_, _> = names.iter().zip(ages.iter()).collect();

    println!("HashMap : {:?}", hash_ages);
}

▶ 출력 결과

HashMap : {"Hyunmin Han": 10, "Donghun Lee": 50}

◆ 해쉬맵 조회

해쉬맵을 조회하는 방법은 두가지입니다.

 

첫번째, 대괄호([])와 HashMap의 키를 활용해서 HashMap의 값 조회(해당하는 HashMap의 키가 없을 경우 프로그램이 panic 될 수 있으니 주의가 필요합니다.)

 

두번째, get 함수에 HashMap의 key를 파라미터로 넘김으로써, HashMap의 값을 Option<&T>으로 조회(해당하는 HashMap의 키가 없을 경우 None을 반환합니다.)

fn main(){
    use std::collections::HashMap;
    
    let mut hash_ages : HashMap<String, u32> = HashMap::new();

    // 신규 등록
    hash_ages.entry(String::from("Hyunmin")).or_insert(28);
    println!("HashMap : {:?}", hash_ages["Hyunmin"]);
    println!("HashMap : {:?}", hash_ages.get("Hyunmin"));
}

▶ 출력 결과

HashMap : 28
HashMap : Some(28)

◆ 해쉬맵 갱신

해쉬맵을 갱신하는 방법은 세가지입니다.

 

첫번째, HashMap에 insert 함수를 통해 데이터를 추가할 때, 기존에 HashMap의 키가 있을 경우 HashMap의 값은 덮어쓰기 되며, 기존 HashMap의 키가 없을 경우 새롭게 추가됩니다.

 

예시) 신규 등록 이후 "Hyunmin" 이라는 HashMap의 키에 해당하는 HashMap의 값이 30으로 덮어쓰기된 것을 확인할 수 있습니다.

fn main(){
    use std::collections::HashMap;
    // HashMap 생성
    let mut hash_ages : HashMap<String, u32> = HashMap::new();
    // 신규 추가
    hash_ages.insert(String::from("Hyunmin"), 29);
    // 덮어쓰기
    hash_ages.insert(String::from("Hyunmin"), 30);
    // 신규 추가
    hash_ages.insert(String::from("Donghun"), 28);

    println!("HashMap : {:?}", hash_ages);
}

▶ 출력 결과

HashMap : {"Hyunmin": 30, "Donghun": 28}

두번째, HashMap에 entry 함수와 or_insert 함수를 활용하여 기존에 HashMap의 키가 있을 경우 등록하지 않고, 기존 HashMap의 키가 없을 경우 새롭게 추가합니다.

fn main(){
    use std::collections::HashMap;
    // HashMap 생성
    let mut hash_ages : HashMap<String, u32> = HashMap::new();
    // 신규 추가
    hash_ages.entry(String::from("Hyunmin")).or_insert(28);
    // 키가 있을 경우 등록하지 않음.
    hash_ages.entry(String::from("Hyunmin")).or_insert(29);
    // 신규 추가
    hash_ages.entry(String::from("Donghun")).or_insert(30);

    println!("HashMap : {:?}", hash_ages);
}

▶ 출력 결과

HashMap : {"Hyunmin": 28, "Donghun": 30}

세번째, HashMap에 entry 함수의 리턴값(&mut [값 타입])에 역참조자(*)를 활용한 HashMap의 값 수정

fn main(){
    use std::collections::HashMap;
    // HashMap 생성
    let mut hash_ages : HashMap<String, u32> = HashMap::new();
    // 신규 등록
    let age = hash_ages.entry(String::from("Hyunmin")).or_insert(28);
    // 역참조자를 활용하여 값 수정
    *age = 29;

    println!("HashMap : {:?}", hash_ages);
}

▶ 출력 결과

HashMap : {"Hyunmin": 29}
반응형
반응형

■ 스트링

스트링은 바이트의 컬렉션 및 바이트들을 텍스트로 통역할 때 유용한 기능을 제공하는 몇몇 메소드로 구현되어 있으며, 문자열 데이터를 갖습니다.


◆ 스트링 생성

스트링을 생성하는 방법은 세가지입니다.

 

첫번째, String 구조체의 new 함수를 활용한 생성

 

두번째, String 구조체의 from 함수를 활용한 생성

 

세번째, Display 트레잇이 구현된 모든 타입에서 to_string 메소드를 이용한 생성  

fn main(){
    // 공백 문자열 생성
    let s1 = String::new();

    // 공백 문자열 생성
    let s1 = String::from("");

    // 공백 문자열 생성
    let s1 = "".to_string();
}

◆ 스트링 갱신

스트링을 갱신하는 방법은 네가지 입니다.

 

첫번째, push_str 함수를 활용한 문자열 추가

 

두번째, push 함수를 활용한 문자 추가

 

세번째, + 연산자를 활용한 문자열 접합

 

네번째, format! 매크로를 활용한 문자열 접합

fn main(){
    // 공백 문자열 생성
    let mut s1 = String::from("");

    // push_str 함수로 문자열 추가
    s1.push_str("A");
    println!("String : {}", s1);

    // push 함수로 문자 추가
    s1.push('B');
    println!("String : {}", s1);

    // + 연산자로 문자열 추가
    s1 = s1 + "C";
    println!("String : {}", s1);

    // format! 매크로로 문자열 추가
    s1 = format!("{}{}",s1, String::from("D"));
    println!("String : {}", s1);
}

▶ 출력 결과

String : A
String : AB
String : ABC
String : ABCD
반응형
반응형

■ 벡터

벡터는 데이터량이 컴파일 타임에 결정되지 않아도 되며, 프로그램 실행 시 늘어나거나 줄어들 수 있기 때문에 힙에 저장됩니다. 또한 메모리 상에 서로 이웃하도록 모든 값을 단일 데이터 구조 안에 하나 이상의 값을 저장하도록 해줍니다. 벡터는 같은 타입의 값만을 저장할 수 있으며, 벡터는 스코프 밖으로 벗어날 시 해제됩니다.


◆ 벡터 생성

벡터를 생성하는 방법은 두 가지입니다.

 

첫번째, 제네릭을 통한 데이터 타입 설정과 Vec 구조체의 new 함수를 통한 벡터 생성 

 

두번째, vec! 매크로를 통한 벡터 생성

fn main(){
    // new 함수를 활용하여 벡터 생성
    let v1 : Vec<u32> = Vec::new();

    // vec! 매크로를 활용하여 벡터 생성
    let v2 : Vec<u32> = vec![1,2,3,4,5];
}

◆ 벡터 요소 읽기

벡터 내의 요소를 읽기 위한 방법은 두 가지입니다.

 

첫번째, 참조자(&) 또는 대괄호([])와 인덱스를 활요한 (인덱스를 벗어날 경우 프로그램이 panic 상태가 될 수 있으니 주의가 필요합니다.)

 

두번째, get 함수에 인덱스 파라미터를 넘김으로써 요소에 접근하며, 반환값으로 Option<&T>를 얻습니다.(인덱스를 벗어날 경우 None이 반환됩니다.)

fn main(){
    let v = vec![10, 20, 30];
    println!("첫번째 요소 : {}", &v[0]);
    println!("두번째 요소 : {:?}", v.get(1));
}

▶ 출력 결과

첫번째 요소 : 10
두번째 요소 : Some(20)

◆ 벡터 요소 추가

벡터를 생성하고 push 함수를 활용하여 요소를 추가합니다.

fn main(){
    // new 함수를 활용하여 벡터 생성
    let mut v1 : Vec<u32> = Vec::new();

    // push 함수를 통해 데이터 추가
    v1.push(1);
    v1.push(2);
    v1.push(3);

    println!("Vec : {:?}", v1);
}

▶ 출력 결과

Vec : [1, 2, 3]

◆ 벡터 요소 수정

벡터의 요소를 수정하기 위해서는 선언 및 초기화시 mut 접두어를 붙여줍니다. 벡터 내의 요소를 수정하는 방법은 두가지입니다.

 

첫번째, 대괄호([])와 인덱스를 활용한 수정

fn main(){
    let mut v = vec![10,20,30];

    println!("첫번째 요소 수정 전 : {}", v[0]);
    
    // 첫번째 요소 수정
    v[0] = 11;

    println!("첫번째 요소 수정 후 : {}", v[0]);
}

▶ 출력 결과

첫번째 요소 수정 전 : 10
첫번째 요소 수정 후 : 11

두번째, 참조(&)와 역참조(*)를 활용한 수정

fn main(){
    let mut v = vec![10,20,30];
    println!("수정 전 : {:?}", v);
    
    // 전체 요소 수정
    for i in &mut v{
        *i += 100;
    }
    println!("수정 후 : {:?}", v);
}

▶ 출력 결과

수정 전 : [10, 20, 30]
수정 후 : [110, 120, 130]
반응형
반응형

■ 패턴 매칭

패턴 매칭에는 match 연산자와 if let 문법이 있습니다.

match 연산자는 다양한 조건을 처리할 때 주로 사용되며, if let 문법은 간결한 흐름을 통해 하나의 패턴만 매칭시키고 나머지는 무시하고 싶을 때 사용됩니다.


◆ match

match는 리터럴 값, 변수명 등 다양한 패턴으로 구성될 수 있습니다.

Java, Go 등에서 자주 사용되는 switch 문법과 유사한 기능을 제공합니다.

match의 패턴은 조건이 될 수 있는 모든 항목을 정의해야 합니다. 만약 패턴 조건에서 무시해도 되는 항목에 경우 변경자(_)를 통해 일괄적으로 무시할 수 있습니다.

1) 반환값이 없는 match

#[derive(Debug)]
enum Gender{
    Male,
    Female,
}

#[derive(Debug)]
enum Info{
    Name(String),
    Age(u32),
    Location{x : i32, y : i32},
    Gender(Gender)
}

fn show_info(info : Info) {
    match info {
        Info::Name(s) => println!("Name: {}", s),
        Info::Age(u) => println!("Age : {}", u),
        Info::Location{x, y} => println!("Location x : {}, y : {}", x, y),
        Info::Gender(gender) => println!("Gender : {:?}", gender)
    }
}

fn main(){
    show_info(Info::Name(String::from("Hyunmin Han")));
    show_info(Info::Age(29));
    show_info(Info::Location{x : 130, y : 80});
    show_info(Info::Gender(Gender::Male));
}

▶ 출력 결과

Name: Hyunmin Han
Age : 29
Location x : 130, y : 80
Gender : Male

2) 반환값이 있는 match

#[derive(Debug)]
enum Gender{
    Male,
    Female,
}

#[derive(Debug)]
enum Info{
    Name(String),
    Age(u32),
    Location{x : i32, y : i32},
    Gender(Gender)
}

fn show_info(info : Info) -> String {
    match info {
        Info::Name(s) => {
            println!("Name: {}", s);
            String::from("Name")
        },
        Info::Age(u) => {
            println!("Age : {}", u);
            String::from("Age")
        },
        Info::Location{x, y} => {
            println!("Location x : {}, y : {}", x, y);
            String::from("Location")
        },
        Info::Gender(gender) => {
            println!("Gender : {:?}", gender);
            String::from("Gender")
        }
    }
}

fn main(){
    let s = show_info(Info::Name(String::from("Hyunmin Han")));
    println!("Select Info : {}\n", s);
    let s = show_info(Info::Age(29));
    println!("Select Info : {}\n", s);
    let s = show_info(Info::Location{x : 130, y : 80});
    println!("Select Info : {}\n", s);
    let s = show_info(Info::Gender(Gender::Male));
    println!("Select Info : {}\n", s);
}

▶ 출력 결과

Name: Hyunmin Han
Select Info : Name

Age : 29
Select Info : Age

Location x : 130, y : 80
Select Info : Location

Gender : Male
Select Info : Gender

3) ( _ ) 변경자 활용

#[derive(Debug)]
enum Gender{
    Male,
    Female,
}

#[derive(Debug)]
enum Info{
    Name(String),
    Age(u32),
    Location{x : i32, y : i32},
    Gender(Gender)
}

fn show_info(info : Info) {
    match info {
        Info::Name(s) => println!("Name: {}", s),
        _ => println!("Something")
    }
}

fn main(){
    show_info(Info::Name(String::from("Hyunmin Han")));
    show_info(Info::Age(29));
    show_info(Info::Location{x : 130, y : 80});
    show_info(Info::Gender(Gender::Male));
}

▶ 출력 결과

Name: Hyunmin Han
Something
Something
Something

◆ if let

if let은 match 와 달리 하나의 패턴만 매칭시키고, 나머지 패턴은 무시하고 싶을 때 주로 사용됩니다.

#[derive(Debug)]
enum Info{
    Name(String),
    Age(u32),
}

fn show_name(info : Info) -> String {
    if let Info::Name(name) = info{
        name
    }else{
        String::from("Something")
    }
}

fn main(){
    // if let 조건 예시 데이터 셋팅
    let s = show_name(Info::Name(String::from("Hyunmin Han")));
    println!("Name : {}", s);

    // else 조건 예시 데이터 셋팅
    let s = show_name(Info::Age(29));
    println!("Name : {}", s);
}

▶ 출력 결과

Name : Hyunmin Han
Name : Something
반응형
반응형

■ 열거형

열거형은 하나의 타입이 가질 수 있는 값들을 다양하게 열거함으로써 타입을 정의할 수 있습니다. 열거형의 항목은 다양한 타입으로 설정할 수 있으며, 열거형은 구조체와 같이 메소드와 연관함수를 구현할 수 있습니다.


◆ 다양한 타입으로 설정

Info 열거형의 항목을 다양하게 String, u32, 구조체, 열거형으로 정의함으로써 열거형의 특징을 확인할 수 있습니다.

#[derive(Debug)]
enum Gender{
    Male,
    Female,
}

#[derive(Debug)]
enum Info{
    // String 타입
    Name(String),
    // u32 타입
    Age(u32),
    // 구조체
    Location{x : i32, y : i32},
    // 열거형
    Gender(Gender)
}
fn main(){
    let name = Info::Name(String::from("Hyunmin han"));
    let age = Info::Age(29);
    let location = Info::Location{ x : 132, y : 80};
    let gender = Info::Gender(Gender::Male);
    
    println!("Name : {:?}", name);
    println!("Age : {:?}", age);
    println!("Location : {:?}", location);
    println!("Gender : {:?}", gender);
}

▶ 출력 결과

Name : Name("Hyunmin han")
Age : Age(29)
Location : Location { x: 132, y: 80 }
Gender : Gender(Male)

◆ 메소드와 연관함수 활용

Info 열거형의 impl(구현부)를 통해 show 메소드와 new_name 연관함수를 구현함으로써, 열거형의 메소드와 연관함수 활용법을 확인할 수 있습니다.

#[derive(Debug)]
enum Info{
    Name(String),
}

impl Info{
    // 메소드 정의
    fn show(&self){
        println!("{:?}", self);
    }

    // 연관 함수 정의
    fn new_name(s : String) -> Info {
        Info::Name(s)
    }
}
fn main(){
    // 연관 함수 호출
    let name  = Info::new_name(String::from("Hyunmin han"));

    // 메소드 호출
    name.show();
}

▶ 출력 결과

Name("Hyunmin han")
반응형
반응형

■ 구조체의 메소드

구조체의 메소드는 구조체의 impl 블록에서 정의해야 하며 메소드의 첫번째 파라미터는 self가 됩니다. 추가적으로 impl의 명은 구조체의 명과 동일해야 하며, 첫번째 파라미터 self는 메소드를 호출하는 인스턴스를 가르킵니다.

struct Person{
    name : String,
    age : u32,
    address : String,
    email : String,
}

// 구조체 구현
impl Person{
    // 메소드 정의
    fn show_person(&self) {
        println!("Name : {}", self.name);
        println!("Age : {}", self.age);
        println!("Address : {}", self.address);
        println!("Email : {}", self.email);
    }
}

fn main(){
    // 인스턴스 생성
    let person = Person{
        name : String::from("Hyunmin han"),
        age : 29,
        address : String::from("서울시 강남구 역삼동"),
        email : String::from("hyunmin@gmail.com"),
    };
    
    // show_person 메소드 호출
    person.show_person();
}

▶ 출력 결과

Name : Hyunmin han
Age : 29
Address : 서울시 강남구 역삼동
Email : hyunmin@gmail.com

■ 구조체의 연관함수

구조체의 연관 함수는 메소드와 다르게 self 파라미터를 갖지 않는 함수이며 구조체::연관함수 문법을 사용하여 호출합니다.

struct Person{
    name : String,
    age : u32,
    address : String,
    email : String,
}

// 구조체 구현
impl Person{
    // 연관 함수 정의
    fn new_person(name : String, age : u32, address : String, email : String) -> Person{
        Person{
            name,
            age,
            address,
            email,
        }
    }
}

fn main(){
    // 연관 함수를 통해 새로운 인스턴스 생성
    let person = Person::new_person(
        String::from("Hyunmin han"),
        29,
        String::from("서울시 강남구 역삼동"),
        String::from("hyunmin@gmail.com"),
    );

    println!("Name : {}", person.name);
    println!("Age : {}", person.age);
    println!("Address : {}", person.address);
    println!("Email : {}", person.email);
}

▶ 출력 결과

Name : Hyunmin han
Age : 29
Address : 서울시 강남구 역삼동
Email : hyunmin@gmail.com
반응형

+ Recent posts