슬라이스 (Slice)

슬라이스 (Slice)

슬라이스(slice)는 한 컬렉션 중 연속적인 일부를 표현하는 것으로 레퍼런스로 리턴한다.

Range 범위

슬라이스는 부분을 표현하기 위해 Range (범위) 문법을 사용하는데, 괄호 안에 [시작위치..마지막위치] 와 같이 표현한다. 예를 들어, 어떤 컬렉션 a의 2번째 요소부터 4번째 요소까지를 표현하고 싶으면, a[1..4]와 같이 표현한다. 컬렉션의 인덱스를 0부터 시작하므로, 2번째 요소의 인덱스는 1이 되고, 4번째 요소의 인덱스는 3이 된다. Range 문법에서 마지막위치는 마지막 요소 인덱스보다 1이 더 많게 적기 때문에서 3+1=4가 된다.

아래 예제는 정수 배열을 가진 변수 a의 일부 (혹은 전체)를 Range 범위로 잘라내는 예들을 표현한 것이다. Range에서 시작위치가 생략되면 0 을 의미하고, 마지막 위치가 생략되면 마지막 요소까지를 가리킨다.

fn main() {
    let a: [i32; 5] = [1,2,3,4,5];

    println!("{:?}", &a[0..2]); // [1, 2] 출력
    println!("{:?}", &a[1..4]); // [2, 3, 4] 출력
    println!("{:?}", &a[..4]);  // [1, 2, 3, 4] 출력
    println!("{:?}", &a[1..]);  // [2, 3, 4, 5] 출력
    println!("{:?}", &a[..]);   // [1, 2, 3, 4, 5] 출력
}

슬라이스

슬라이스는 레퍼런스로서 소유권(Ownership)을 갖지 않는다. 즉, 어떤 컬렉션에 대해 슬라이스를 만들면, 컬렉션 변수의 소유권이 이전되지 않는다.

아래 예제는 정수 배열을 가진 변수 numbers를 슬라이스로 get_first_two() 함수로 전달하고, 배열의 처음 2개의 요소를 다시 슬라이스(&[i32])로 리턴하는 예이다.

fn main() {
    let numbers: [i32; 5] = [1,2,3,4,5];
    let first2 = get_first_two(&numbers);
    
    println!("{:?}", first2);
}

fn get_first_two(data: &[i32]) -> &[i32] {
    if data.len() < 2 {
        panic!("invalid data");
    }
    &data[0..2]
}

문자열 슬라이스: &str

슬라이스 중에 가장 많이 사용되는 것 중의 하나는 문자열 슬라이스(string slice)이다. 문자열 슬라이스는 String 타입의 문자열의 일부를 취하는 슬라이스로서 &str 타입으로 표현한다.

아래 예제에서 변수 s는 String 타입인데, 이 변수에 Range를 지정하여 문자열 슬라이스 &str 타입의 변수 s1과 s2를 만들었다. 이때의 변수 s1과 s2는 레퍼런스 타입으로 변수 s의 소유권을 이전받지 않는다. 따라서, 소유권 이전 없이 여러 개의 문자열 슬라이스를 만들 수 있다.

fn main() {
    let s: String = String::from("hello");

    let s1: &str = &s[1..4]; // "ell"
    let s2: &str = &s[2..];  // "llo"

    println!("{:?},{:?}", s1, s2);
}

문자열 슬라이스를 그림으로 표현하면 다음과 같다. 위 예제의 변수 s에 대해 s[1..4]이 슬라이스 s1이라고 했을 때, s1은 &str 타입으로 시작위치를 가리키는 포인터와 슬라이스의 길이를 가리키는 Len 데이타를 갖게 된다.

Rust 문자열 슬라이스

아래 예제는 문자열 슬라이스를 함수의 파라미터로 전달하고, 다시 문자열 슬라이스를 리턴받는 예이다. 문자열 리터럴은 (전체 문자열을 갖는) 슬라이스이고 &str 타입이다. 함수 get_first_two()의 파라미터로 문자열 슬라이스 s를 전달하고, 함수 내에 처음 2개의 문자를 발췌하여 이를 다시 ' 문자열 슬라이스 &str 타입으로 리턴하고 있다.

fn main() {
    let s = "hello world";

    let first2: &str = get_first_two(s);
    
    println!("{}", first2);
}

fn get_first_two(data: &str) -> &str {
    if data.len() < 2 {
        panic!("invalid data");
    }
    &data[0..2]
}

This site is not affiliated with or endorsed by the Rust Foundation or Rust Project.