在逆序情况下如何进行条件迭代?

huangapple go评论51阅读模式
英文:

How do I conditionally iterate in reverse?

问题

以下是您提供的代码的翻译部分:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6];

    print(&numbers, false);
    print(&numbers, true);
}

fn print(what: &[i32], reverse: bool) {
    let iter = what.iter();

    if reverse {
        iter = iter.rev();
    }

    for n in iter {
        println!("{n}");
    }
}

这是您收到的错误:

// 错误:
类型不匹配
期望结构体 `std::slice::Iter<&'_ , _>`
   找到结构体 `Rev<std::slice::Iter<'_, _>>`

您想要实现所需行为的方法是令iter的类型一致。在Rust中,可以使用Box<dyn Iterator>来处理这种情况。这里是修复后的代码:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6];

    print(&numbers, false);
    print(&numbers, true);
}

fn print(what: &[i32], reverse: bool) {
    let mut iter: Box<dyn Iterator<Item = &i32>> = if reverse {
        Box::new(what.iter().rev())
    } else {
        Box::new(what.iter())
    };

    while let Some(n) = iter.next() {
        println!("{:?}", n);
    }
}

这段代码将允许您在基于布尔参数的条件下切换迭代器的方向,而不会出现类型不匹配的错误。

英文:

I want to switch the direction of an iterator based on a boolean parameter. I tried the following approach, but it ends with a compile error:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6];

    print(&amp;numbers, false);
    print(&amp;numbers, true);
}

fn print(what: &amp;[i32], reverse: bool) {
    let iter = what.iter();

    if reverse {
        iter = iter.rev();
    }

    for n in iter {
        println!(&quot;{n}&quot;);
    }
}

This is the error I receive:

// Error:
mismatched types
expected struct `std::slice::Iter&lt;&#39;_, _&gt;`
   found struct `Rev&lt;std::slice::Iter&lt;&#39;_, _&gt;&gt;`

How could I implement my desired behavior?

答案1

得分: 1

You can do it using dynamic dispatch as explained here like so:

fn iterateMyData(a: &mut VecDeque<A>, b: &mut BTreeMap<u64, VecDeque<B>>) {
    // Do something.

    let reverse: bool = a.front().unwrap().reverse;

    for a_value in a.iter_mut() {
        let mut temp_iter1;
        let mut temp_iter2;
        let mut iter: &mut dyn Iterator<Item = _> = if reverse {
            temp_iter1 = b.values_mut().rev();
            &mut temp_iter1
        } else {
            temp_iter2 = b.values_mut();
            &mut temp_iter2
        };
        
        for b_vec in iter {
            // Do something.
        }
    }
}

and the rustexplorer link.

However, as already noted in the linked thread above, it is probably easier and better to use an enum (crate) like either like so:

let mut iter =
    if reverse { 
        Either::Left(b.values_mut().rev()) 
    }
    else { 
        Either::Right(b.values_mut()) 
    };

Also, in the case that you just need to print out the iterator in a certain direction based on a flag, this can be done without external crates as follows:

fn main() {

    let numbers = vec![1, 2, 3, 4, 5, 6];

    print(&numbers, false);
    print(&numbers, true);
        
}

fn print(what: &[i32], reverse: bool) {
    //match statement condition check
    match reverse {
        true => {
            for n in what.iter().rev() {
                println!("{n}");
            }
        },
        false => {
            for n in what.iter() {
                println!("{n}");
            }
            
        },
    }
}

(Note: The code you provided contains HTML escape codes, which I've left as is.)

英文:

You can do it using dynamic dispatch as explained here like so:

fn iterateMyData(a: &amp;mut VecDeque&lt;A&gt;, b: &amp;mut BTreeMap&lt;u64, VecDeque&lt;B&gt;&gt;) {
    // Do something.

    let reverse: bool = a.front().unwrap().reverse;

    for a_value in a.iter_mut() {
        let mut temp_iter1;
        let mut temp_iter2;
        let mut iter: &amp;mut dyn Iterator&lt;Item = _&gt; = if reverse {
            temp_iter1 = b.values_mut().rev();
            &amp;mut temp_iter1
        } else {
            temp_iter2 = b.values_mut();
            &amp;mut temp_iter2
        };
        
        for b_vec in iter {
            // Do something.
        }
    }
}

and the rustexplorer link.

However as already noted in the linked thread above, it is probably easier and better to use an enum (crate) like either like so

let mut iter =
    if reverse { 
        Either::Left(b.values_mut().rev()) 
    }
    else { 
        Either::Right(b.values_mut()) 
    };

Also in the case that you just need to print out the iterator in a certain direction based on a flag this can be done without external crates as follows:

fn main() {

    let numbers = vec![1, 2, 3, 4, 5, 6];

    print(&amp;numbers, false);
    print(&amp;numbers, true);
        
}

fn print(what: &amp;[i32], reverse: bool) {
    //match statement condition check
    match reverse {
        true =&gt; {
            for n in what.iter().rev() {
                println!(&quot;{n}&quot;);
            }
        },
        false =&gt; {
            for n in what.iter() {
                println!(&quot;{n}&quot;);
            }
            
        },
    }
}

huangapple
  • 本文由 发表于 2023年4月10日 19:37:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75976750.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定