这个循环如何变成惯用的 Rust?
How can this loop be turned into idiomatic Rust?
这是一个有效的 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
}
它有效,但该循环看起来不像惯用的 Rust。它使用手动管理的索引索引到数组中,非常类似于 C 中的 for
循环。
有没有办法使用 Rust 迭代器实现相同的结果?我认为 chunked_exact
可以迭代 src
,但是 dst
呢? zip
和 src.chunked_exact
可以用什么迭代器分块写入 dst
?
什么是 "idiomatic" 可以见仁见智,但您可以使用更多迭代器方法,例如 zip
和 chunks_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
}
我使用了 chunks_exact
和 chunks_exact_mut
而不是 chunks
,因为它保证切片具有请求的长度,如果需要它们可以单独使用。这似乎与您的原始代码相匹配,它将长度四舍五入为精确的步数。
我会同意的:
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()
}
或者如果您愿意:
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()
}
不确定您是否发现其中之一更好。
这是一个有效的 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
}
它有效,但该循环看起来不像惯用的 Rust。它使用手动管理的索引索引到数组中,非常类似于 C 中的 for
循环。
有没有办法使用 Rust 迭代器实现相同的结果?我认为 chunked_exact
可以迭代 src
,但是 dst
呢? zip
和 src.chunked_exact
可以用什么迭代器分块写入 dst
?
什么是 "idiomatic" 可以见仁见智,但您可以使用更多迭代器方法,例如 zip
和 chunks_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
}
我使用了 chunks_exact
和 chunks_exact_mut
而不是 chunks
,因为它保证切片具有请求的长度,如果需要它们可以单独使用。这似乎与您的原始代码相匹配,它将长度四舍五入为精确的步数。
我会同意的:
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()
}
或者如果您愿意:
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()
}
不确定您是否发现其中之一更好。