英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论