简体   繁体   English

如何将此循环转换为惯用的Rust?

[英]How can this loop be turned into idiomatic Rust?

Here is a working Rust function: 这是一个正常工作的Rust函数:

fn foo(src: &[u8]) -> Vec<u8> {
    let dst_len = (src.len() / 3) * 4;
    let mut dst = vec![0 as u8; dst_len];

    let mut si = 0;
    let mut di = 0;
    let n = (src.len() / 3) * 3;
    for _ in (0 .. n).step_by(3) {
        let v = bar(src[si], src[si+1], src[si+2]);
        dst[di+0] = baz(v, 0);
        dst[di+1] = baz(v, 1);
        dst[di+2] = baz(v, 2);
        dst[di+3] = baz(v, 3);
        si += 3;
        di += 4;
    }

    dst
}

It works but that loop doesn't seem like idiomatic Rust. 它可以工作,但是该循环看起来不像惯用的Rust。 It indexes into arrays using manually managed indices, pretty much like a for loop in C. 它使用手动管理的索引索引到数组中,非常类似于C中的for循环。

Is there a way to achieve the same result using Rust iterators? 有没有一种方法可以使用Rust迭代器达到相同的结果? I think chunked_exact would work for iterating over src , but what about dst ? 我认为chunked_exact可以在src迭代,但是dst呢? What iterator could I zip with src.chunked_exact to write into dst in chunks? 我可以使用src.chunked_exact zip哪些迭代器以成块地写入dst

What is "idiomatic" can be a matter of opinion, but you can make use of more iterator methods, like zip and chunks_exact_mut : 什么是“惯用的”可以是一个问题,但是您可以使用更多的迭代器方法,例如zipchunks_exact_mut

fn foo(src: &[u8]) -> Vec<u8> {
    let dst_len = (src.len() / 3) * 4;
    let mut dst = vec![0 as u8; dst_len];
    for (s, d) in src.chunks_exact(3).zip(dst.chunks_exact_mut(4)) {
        let v = bar(s[0], s[1], s[2]);
        d[0] = baz(v, 0);
        d[1] = baz(v, 1);
        d[2] = baz(v, 2);
        d[3] = baz(v, 3);
    }
    dst
}

I used chunks_exact and chunks_exact_mut rather than chunks because it guarantees that the slice has the requested length, making them available separately if you need them. 我使用chunks_exactchunks_exact_mut而不是chunks因为它可以保证切片具有请求的长度,并在需要时使其分开可用。 This seems to match your original code, which rounds off the length to an exact number of steps. 这似乎与您的原始代码匹配,该代码将长度四舍五入为确切的步数。

I would go with that: 我会同意的:

fn foo(src: &[u8]) -> Vec<u8> {
    src.chunks_exact(3)
        .map(|s| bar(s[0], s[1], s[2]))
        .flat_map(|v| (0..4).map(move |i| baz(v, i)))
        .collect()
}

Or if you prefer: 或者,如果您愿意:

fn foo(src: &[u8]) -> Vec<u8> {
    src.chunks_exact(3)
        .map(|s| bar(s[0], s[1], s[2]))
        .flat_map(|v| vec![baz(v, 0), baz(v, 1), baz(v, 2), baz(v, 3)])
        .collect()
}

Not sure if you find one of them better. 不知道您是否找到更好的一种。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM