IT이야기

Iterator::map이 Result::Err을 반환할 때 반복을 중지하고 오류를 반환하려면

cyworld 2021. 10. 12. 20:16
반응형

Iterator::map이 Result::Err을 반환할 때 반복을 중지하고 오류를 반환하려면 어떻게 해야 합니까?


다음을 반환하는 함수가 있습니다 Result.

fn find(id: &Id) -> Result<Item, ItemError> {
    // ...
}

그런 다음 다음과 같이 사용합니다.

let parent_items: Vec<Item> = parent_ids.iter()
    .map(|id| find(id).unwrap())
    .collect();

map반복 내에서 실패하는 경우를 어떻게 처리 합니까?

사용할 수 있다는 것을 알고 flat_map있으며 이 경우 오류 결과는 무시됩니다 .

let parent_items: Vec<Item> = parent_ids.iter()
    .flat_map(|id| find(id).into_iter())
    .collect();

Result의 반복자는 성공 상태에 따라 0 또는 1개의 항목을 가지며 0이면 flat_map필터링합니다.

그러나 오류 무시 하고 싶지 않습니다. 대신 전체 코드 블록을 중지하고 새 오류를 반환하고 싶습니다(지도 내에서 발생한 오류를 기반으로 하거나 기존 오류를 전달함).

Rust에서 이것을 가장 잘 처리하는 방법은 무엇입니까?


Result 구현FromIterator 하므로 Result외부 로 이동할 수 있으며 나머지는 반복자가 처리합니다(오류가 발견되면 반복 중지 포함).

#[derive(Debug)]
struct Item;
type Id = String;

fn find(id: &Id) -> Result<Item, String> {
    Err(format!("Not found: {:?}", id))
}

fn main() {
    let s = |s: &str| s.to_string();
    let ids = vec![s("1"), s("2"), s("3")];

    let items: Result<Vec<_>, _> = ids.iter().map(find).collect();
    println!("Result: {:?}", items);
}

운동장


이 답변은 1.0 이전 버전의 Rust와 관련이 있으며 필요한 기능이 제거되었습니다.

이를 위해 std::result::fold기능을 사용할 수 있습니다 . 첫 번째 를 만난 후 반복을 멈춥니다 Err.

방금 작성한 예제 프로그램:

fn main() {
  println!("{}", go([1, 2, 3]));
  println!("{}", go([1, -2, 3]));
}

fn go(v: &[int]) -> Result<Vec<int>, String> {
    std::result::fold(
        v.iter().map(|&n| is_positive(n)),
        vec![],
        |mut v, e| {
            v.push(e);
            v
        })
}

fn is_positive(n: int) -> Result<int, String> {
    if n > 0 {
        Ok(n)
    } else {
        Err(format!("{} is not positive!", n))
    }
}

산출:

Ok([1, 2, 3])
Err(-2 is not positive!)

데모

ReferenceURL : https://stackoverflow.com/questions/26368288/how-do-i-stop-iteration-and-return-an-error-when-iteratormap-returns-a-result

반응형