英文:
In Rust I want to assign a given value to all elements of nested vectors
问题
I am trying to build a function similar to np.zeros from Python for Rust.
我正在尝试构建一个类似于Python中的np.zeros的函数,用于Rust。
I would like to do something like:
我想做类似这样的事情:
trait VectorHelper {
fn fill_with<A>(&mut self, value: A) -> &mut Self;
}
impl<T: VectorHelper> VectorHelper for Vec<T> {
fn fill_with<A>(&mut self, value: A) -> &mut Self {
for elem in self.iter() {
if elem.is_vec() {
elem.fill_with(value);
} else {
*elem = value;
}
}
self
}
}
But I do not know how to get this to work, because there is no general conversion for A to T.
What can I do to make the compiler accept this assignment: "*elem = value"?
但是我不知道如何使其工作,因为没有通用的A到T的转换。我该如何让编译器接受这个赋值:"*elem = value"?
英文:
I am trying to build a function similar to np.zeros from Python for Rust.
I would like to do something like:
trait VectorHelper {
fn fill_with<A>(&mut self, value: A) -> &mut Self;
}
impl<T: VectorHelper> VectorHelper for Vec<T> {
fn fill_with<A>(&mut self, value: A) -> &mut Self {
for elem in self.iter() {
if elem.is_vec() {
elem.fill_with(value);
} else {
*elem = value;
}
}
self
}
}
But I do not know how to get this to work, because there is no general conversion for A to T.
What can I do to make the compiler accept this assignment: "*elem = value"?
答案1
得分: 0
以下是翻译好的部分:
"由于似乎没有我预期的解决方案,我必须坚持使用我的临时解决方案,直到有一个合适的解决方案。但希望有更好的方法来做这个。我将很高兴了解它们。"
trait VectorHelper {
fn fill_with(&mut self, value: f64) -> &mut Self;
}
impl VectorHelper for Vec<f64> {
fn fill_with(&mut self, value: f64) -> &mut Self {
for elem in self.iter_mut() {
*elem = value;
}
self
}
}
impl VectorHelper for Vec<Vec<f64>> {
fn fill_with(&mut self, value: f64) -> &mut Self {
for k in self.iter_mut() {
for j in k.iter_mut() {
*j = value;
}
}
self
}
}
impl VectorHelper for Vec<Vec<Vec<f64>>> {
fn fill_with(&mut self, value: f64) -> &mut Self {
for k in self.iter_mut() {
for j in k.iter_mut() {
for l in j.iter_mut() {
*l = value;
}
}
}
self
}
}
请注意,我已经移除了 HTML 编码,以便更清晰地阅读代码。
英文:
As it seems that there is no solution how I intended it, I have to stick with my workaround, until there is a proper solution.
But hopefully there are better ways to do this.
I would be pleased to learn about them.
trait VectorHelper {
fn fill_with(&mut self, value: f64) -> &mut Self;
}
impl VectorHelper for Vec<f64> {
fn fill_with(&mut self, value:f64) -> &mut Self {
for elem in self.iter_mut() {
*elem = value;
}
self
}
}
impl VectorHelper for Vec<Vec<f64>> {
fn fill_with(&mut self, value:f64) -> &mut Self {
for k in self.iter_mut() {
for j in k.iter_mut() {
*j = value;
}
}
self
}
}
impl VectorHelper for Vec<Vec<Vec<f64>>> {
fn fill_with(&mut self, value:f64) -> &mut Self {
for k in self.iter_mut() {
for j in k.iter_mut() {
for l in j.iter_mut() {
*l = value;
}
}
}
self
}
}
答案2
得分: 0
以下是您要翻译的代码部分:
虽然像您想要的精确实现不太可能,但您仍然可以通过一种通用实现来处理除第一个之外的所有附加层:
```rust
impl<V: Clone, T: VectorHelper<V>> VectorHelper<V> for Vec<T> {
fn fill_with(&mut self, value: V) -> &mut Self {
for elem in &mut *self {
elem.fill_with(value.clone());
}
self
}
}
然后,对于每个基本类型,您可以实现一次该特性(可能通过宏以减少重复):
macro_rules! impl_vector_helper {
($t:ty) => {
impl VectorHelper<$t> for Vec<$t> {
fn fill_with(&mut self, value: $t) -> &mut Self {
self.fill(value);
self
}
}
};
($($t:ty),* $(,)?) => {
$(impl_vector_helper!{$t})*
};
}
impl_vector_helper! {
u8, u16, u32, u64,
i8, i16, i32, i64,
f32, f64,
&'static str,
}
您只需将函数中的泛型移到特性中:
trait VectorHelper<V> {
fn fill_with(&mut self, value: V) -> &mut Self;
}
希望这对您有所帮助。
英文:
While the exact implementation like you want it isn't possible you can still handle all the additional layers but the first by a blanket implementation:
impl<V: Clone, T: VectorHelper<V>> VectorHelper<V> for Vec<T> {
fn fill_with(&mut self, value: V) -> &mut Self {
for elem in &mut *self {
elem.fill_with(value.clone());
}
self
}
}
Then for each base type you can implement the trait once (possibly by a macro to reduce duplication):
macro_rules! impl_vector_helper {
($t:ty) => {
impl VectorHelper<$t> for Vec<$t> {
fn fill_with(&mut self, value: $t) -> &mut Self {
self.fill(value);
self
}
}
};
($($t:ty),* $(,)?) => {
$(impl_vector_helper!{$t})*
};
}
impl_vector_helper! {
u8, u16, u32, u64,
i8, i16, i32, i64,
f32, f64,
&'static str,
}
You just have to move the generic from the function to the trait:
trait VectorHelper<V> {
fn fill_with(&mut self, value: V) -> &mut Self;
}
答案3
得分: 0
Here are the translated parts:
可以将特性更改为类似以下内容的内容
```rust
trait VectorHelper<T> {
fn fill_with<A>(&mut self, value: A) -> &mut Self
where
A: Into<T>;
}
然后,您可以按如下方式实现它
impl<T> VectorHelper<T> for Vec<T>
where
T: VectorHelper<T>,
{
fn fill_with<A>(&mut self, value: A) -> &mut Self
where
A: Into<T>,
{
for elem in self.iter() {
if elem.is_vec() {
elem.fill_with(value);
} else {
*elem = value.into();
}
}
self
}
}
然而,这段代码由于其他几个原因而无法正常工作,我假设这仅用作询问困扰您的特定部分(转换)的示例。如果不是这样,您有两个选择:
1. 手动降到向量的底层并用所需的值填充它们:
let mut v1 = vec![1, 2, 3, 4, 5];
v1.fill(0);
assert_eq!(v1, vec![0, 0, 0, 0, 0]);
let mut v2 = vec![vec![1, 2], vec![3, 4, 5]];
v2.iter_mut().for_each(|v| v.fill(0));
assert_eq!(v2, vec![vec![0, 0], vec![0, 0, 0]]);
let mut v3 = vec![vec![vec![1], vec![2]], vec![vec![3, 4], vec![5]]];
v3.iter_mut()
.for_each(|v| v.iter_mut().for_each(|v| v.fill(0)));
assert_eq!(v3, vec![vec![vec![0], vec![0]], vec![vec![0, 0], vec![0]]]);
2. 实现自定义 NestedVec:
enum NestedVec<T> {
Vec(Vec<NestedVec<T>>),
Val(T),
}
impl<T> NestedVec<T> {
fn fill<A>(&mut self, value: A)
where
A: Clone + Into<T>,
{
match self {
Self::Vec(vec) => vec.iter_mut().for_each(|elem| elem.fill(value.clone())),
Self::Val(val) => {
*val = value.into();
}
}
}
}
let mut nested = NestedVec::Vec(vec![
NestedVec::Vec(vec![
NestedVec::Val(2),
NestedVec::Vec(vec![NestedVec::Val(3), NestedVec::Val(4)]),
]),
NestedVec::Val(5),
]);
nested.fill(0);
您可能还希望实现用于构造此结构、插入元素等的辅助函数、特性和/或宏。
<details>
<summary>英文:</summary>
You could change the trait to something like
```rust
trait VectorHelper<T> {
fn fill_with<A>(&mut self, value: A) -> &mut Self
where
A: Into<T>;
}
and then you could implement it as
impl<T> VectorHelper<T> for Vec<T>
where
T: VectorHelper<T>,
{
fn fill_with<A>(&mut self, value: A) -> &mut Self
where
A: Into<T>,
{
for elem in self.iter() {
if elem.is_vec() {
elem.fill_with(value);
} else {
*elem = value.into();
}
}
self
}
}
This code, however, will not work for several other reasons, and I assume this was only used as an example to ask for a specific part that troubles you (the conversion). If not, you have two options:
1. Manually descend to the bottom level of your vectors and fill them with desired value:
let mut v1 = vec![1, 2, 3, 4, 5];
v1.fill(0);
assert_eq!(v1, vec![0, 0, 0, 0, 0]);
let mut v2 = vec![vec![1, 2], vec![3, 4, 5]];
v2.iter_mut().for_each(|v| v.fill(0));
assert_eq!(v2, vec![vec![0, 0], vec![0, 0, 0]]);
let mut v3 = vec![vec![vec![1], vec![2]], vec![vec![3, 4], vec![5]]];
v3.iter_mut()
.for_each(|v| v.iter_mut().for_each(|v| v.fill(0)));
assert_eq!(v3, vec![vec![vec![0], vec![0]], vec![vec![0, 0], vec![0]]]);
2. Implement custom NestedVec<T>
enum NestedVec<T> {
Vec(Vec<NestedVec<T>>),
Val(T),
}
impl<T> NestedVec<T> {
fn fill<A>(&mut self, value: A)
where
A: Clone + Into<T>,
{
match self {
Self::Vec(vec) => vec.iter_mut().for_each(|elem| elem.fill(value.clone())),
Self::Val(val) => {
*val = value.into();
}
}
}
}
let mut nested = NestedVec::Vec(vec![
NestedVec::Vec(vec![
NestedVec::Val(2),
NestedVec::Vec(vec![NestedVec::Val(3), NestedVec::Val(4)]),
]),
NestedVec::Val(5),
]);
nested.fill(0);
You'll probably want to also implement helper functions, traits and/or macros for constructing this struct, inserting elements, etc.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论