function add(...args){
if (args.length === 0) return [];
const a = args[0];
let res = [];
for (let i = 0; i < a.length; i++){
const elements = args.map(x => x[i]);
res.push(Array.isArray(a[i]) ? add(...elements) : elements.reduce((a, b) => a + b));
}
return res;
}
console.log(add([[1]], [[2]])); // [[3]]
console.log(add([1], [2])); // [3]
console.log(add([1, 2], [3, 4])); // [4, 6]
console.log(add([[1, 2]], [[3, 4]])); // [[4, 6]]
i want to create function which adds any amount of arrays with any depth.
i have 2 arrays
let myArray: Vec<...> = vec![...]; // and
let myArrayChanges: Vec<...> = vec![...];
how sum them with this function in rust if myArray
can have diffrent depth depending on situation
Expectations: i expect working rust function
In the end, your function is recursively "adding" values together, where adding arrays creates a new array based on element-wise "adding".
So all we need to know is how to "add" numbers and how to "add" arrays in such a fashion. For handling types generically we need traits; there is already a standard Add
trait so lets call ours Combine
:
trait Combine {
fn combine(self, other: Self) -> Self;
}
impl Combine for i32 {
fn combine(self, other: i32) -> i32 {
self + other
}
}
impl<T> Combine for Vec<T> where T: Combine {
fn combine(self, other: Vec<T>) -> Vec<T> {
self.into_iter().zip(other).map(|(s, o)| s.combine(o)).collect()
}
}
And that's really it, the Vec
implementation already knows how to handle itself recursively (such that Vec<Vec<i32>>
automatically works as well).
fn add<T: Combine>(a: T, b: T) -> T {
a.combine(b)
}
fn main() {
let a = vec![1i32, 2, 3, 4];
let b = vec![5i32, 6, 7, 8];
println!("{:?}", add(a, b));
let a = vec![vec![1i32, 2], vec![3, 4]];
let b = vec![vec![5i32, 6], vec![7, 8]];
println!("{:?}", add(a, b));
}
[6, 8, 10, 12]
[[6, 8], [10, 12]]
NOTES:
Combine
automatically worked from the pre-existing Add
(assuming that is your intention) but unfortunately that means a "conflict" with Add
for Vec
- which doesn't exist but the compiler doesn't allow us to write code assuming it doesn't. So you will need to define Combine
for all the types you're going to want to "add" yourself (macros can help if you need a lot).add(...args)
such that it can be passed an arbitrary number of arguments, but that isn't a thing in Rust. If you want that then you could make a macro to iteratively build .combine(...)
or it'd be better to just make a function that takes an iterator of values to combine - an easy .reduce
away.