在Rust中,我想将给定值分配给嵌套向量的所有元素。

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

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&lt;A&gt;(&amp;mut self, value: A) -&gt; &amp;mut Self;
}
impl&lt;T: VectorHelper&gt; VectorHelper for Vec&lt;T&gt; {
  fn fill_with&lt;A&gt;(&amp;mut self, value: A) -&gt; &amp;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(&amp;mut self, value: f64) -&gt; &amp;mut Self;
}
impl VectorHelper for Vec&lt;f64&gt; {
  fn fill_with(&amp;mut self, value:f64) -&gt; &amp;mut Self {
    for elem in self.iter_mut() {
      *elem = value;
    }
    self
  }
}
impl VectorHelper for Vec&lt;Vec&lt;f64&gt;&gt; {
  fn fill_with(&amp;mut self, value:f64) -&gt; &amp;mut Self {
    for k in self.iter_mut() {
      for j in k.iter_mut() {
        *j = value;
      }
    }
    self
  }
}
impl VectorHelper for Vec&lt;Vec&lt;Vec&lt;f64&gt;&gt;&gt; {
  fn fill_with(&amp;mut self, value:f64) -&gt; &amp;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&lt;V: Clone, T: VectorHelper&lt;V&gt;&gt; VectorHelper&lt;V&gt; for Vec&lt;T&gt; {
  fn fill_with(&amp;mut self, value: V) -&gt; &amp;mut Self {
    for elem in &amp;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) =&gt; {
        impl VectorHelper&lt;$t&gt; for Vec&lt;$t&gt; {
            fn fill_with(&amp;mut self, value: $t) -&gt; &amp;mut Self {
                self.fill(value);
                self
            }
        }
    };
    ($($t:ty),* $(,)?) =&gt; {
        $(impl_vector_helper!{$t})*
    };
}

impl_vector_helper! {
    u8, u16, u32, u64,
    i8, i16, i32, i64,
    f32, f64,
    &amp;&#39;static str,
}

You just have to move the generic from the function to the trait:

trait VectorHelper&lt;V&gt; {
    fn fill_with(&amp;mut self, value: V) -&gt; &amp;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&lt;T&gt; {
    fn fill_with&lt;A&gt;(&amp;mut self, value: A) -&gt; &amp;mut Self
    where
        A: Into&lt;T&gt;;
}

and then you could implement it as

impl&lt;T&gt; VectorHelper&lt;T&gt; for Vec&lt;T&gt;
where
    T: VectorHelper&lt;T&gt;,
{
    fn fill_with&lt;A&gt;(&amp;mut self, value: A) -&gt; &amp;mut Self
    where
        A: Into&lt;T&gt;,
    {
        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&lt;T&gt; {
    Vec(Vec&lt;NestedVec&lt;T&gt;&gt;),
    Val(T),
}

impl&lt;T&gt; NestedVec&lt;T&gt; {
    fn fill&lt;A&gt;(&amp;mut self, value: A)
    where
        A: Clone + Into&lt;T&gt;,
    {
        match self {
            Self::Vec(vec) =&gt; vec.iter_mut().for_each(|elem| elem.fill(value.clone())),
            Self::Val(val) =&gt; {
                *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.

huangapple
  • 本文由 发表于 2023年4月13日 18:21:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76004311.html
匿名

发表评论

匿名网友

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

确定