Flatten을위한 Iterator 대 IntoIterator

Oct 06 2020

나는 반복기를 가지고 놀고 있고 반복기가 Flatten어떻게 작동하는지 더 잘 이해하기 위해 사용 하고 있습니다. 이 예 :

assert_eq!(vec![1, 2].iter().flatten().count(), 2);

컴파일하지 않고 오류를 제공합니다 (주요 주요 오류).

error[E0277]: `&{integer}` is not an iterator
  --> src/lib.rs:59:38
   |
59 |         assert_eq!(vec![1, 2].iter().flatten().count(), 2);
   |                                      ^^^^^^^ `&{integer}` is not an iterator
   |
   = help: the trait `std::iter::Iterator` is not implemented for `&{integer}`
   = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&{integer}`

나를 혼란스럽게하는 것은 구현 Flatten하기 위해 중첩 Item이 필요 하다는 것 IntoIterator입니다. 나는 rustdocs에서 이것을 확인했습니다.

pub struct Flatten<I> 
where
    I: Iterator,
    <I as Iterator>::Item: IntoIterator

문서 준비에서 IntoIterator는 유형이 반복기로 변환되는 방법을 정의하는 방법을 제공합니다. 왜 특성이 바운드 될 수 <I as Iterator>::Item: Iterator없습니까? 분명히 중첩 된 항목이를 구현 하면 중첩 된 항목이 반복자 자체 여야하므로 Iterator동일한 결과를 얻 Flatten습니다. IntoIterator대신 사용할 수있는 차이점 / 이점은 무엇입니까 ?

답변

1 twotwotwo Oct 06 2020 at 11:18

IntoIterator보다는 Requiring을 Iterator사용하면 반복기 컬렉션 외에도 컬렉션 컬렉션을 평면화 할 수 있습니다.

컬렉션 타입은, 예를 들어 Vec, 만약 그렇다면, 반복자 유형과 다른 flatten것으로 항목을 요구 Iterator당신이 평평하지 못했습니다의 Vec의 Vec의를.

IntoIterator하나 이상의 다른 컬렉션 (또는 반복자!) 과 같이 반복기 로 변환 할 수있는 형식을 나타냅니다 Vec. 예를 들어 이것은 작동합니다.

fn main() {
    let nested_vec: Vec<Vec<i32>> = vec![vec![1, 2], vec![3, 4]];
    let flat_vec: Vec<i32> = nested_vec.into_iter().flatten().collect();
    println!("{:?}", flat_vec);
}

Playground에서이 예제를 시도해 볼 수 있습니다 . into_iter()대신 위를 사용하면 s에 대한 참조 가 아니라 s를 iter()반복 합니다. ( 대신 제안 해 주신 Cerberus에게 감사드립니다 .)i32i32into_iter()copied()

( 문서의 "외부 유형에 대한 구현"섹션에서IntoIterator 구현이 있는 몇 가지 유형을 더 볼 수 있습니다 .)