lowdash 0.5.3

A Lodash inspired utility library to manipulate array and object for Rust
Documentation
/// Calculate the product of values obtained by applying a function to each element in a collection.
/// If the collection is empty, returns 1 (multiplicative identity).
/// Works with any numeric type that implements `std::ops::Mul` and can be copied.
///
/// # Arguments
/// * `collection` - A slice of items.
/// * `iteratee` - A function that takes an item from the collection and returns a number.
///
/// # Returns
/// * `T` - The product of all numbers generated by the iteratee function.
///
/// # Examples
/// ```rust
/// use lowdash::product_by;
///
/// let numbers = vec![1, 2, 3, 4];
/// let result = product_by(&numbers, |x| x * 2);
/// assert_eq!(result, 384); // (1*2) * (2*2) * (3*2) * (4*2)
/// ```
///
/// ```rust
/// use lowdash::product_by;
///
/// #[derive(Debug)]
/// struct Rectangle {
///     width: f64,
///     height: f64,
/// }
///
/// let rectangles = vec![
///     Rectangle { width: 2.0, height: 3.0 },
///     Rectangle { width: 4.0, height: 5.0 },
/// ];
///
/// let total_area = product_by(&rectangles, |r| r.width * r.height);
/// assert_eq!(total_area, 120.0); // (2*3) * (4*5)
/// ```
pub fn product_by<T, R>(collection: &[T], iteratee: impl Fn(&T) -> R) -> R
where
    R: std::ops::Mul<Output = R> + From<u8> + Copy,
{
    if collection.is_empty() {
        return R::from(1);
    }

    collection
        .iter()
        .fold(R::from(1), |acc, item| acc * iteratee(item))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_product_by_integers() {
        let numbers = vec![1, 2, 3, 4];
        let result = product_by(&numbers, |x| x * 2);
        assert_eq!(result, 384);
    }

    #[test]
    fn test_product_by_floats() {
        let numbers = vec![1.5, 2.0, 3.0];
        let result = product_by(&numbers, |x| x * 2.0);
        assert_eq!(result, 72.0);
    }

    #[test]
    fn test_product_by_empty() {
        let empty: Vec<i32> = vec![];
        let result = product_by(&empty, |x| x * 2);
        assert_eq!(result, 1);
    }

    #[test]
    fn test_product_by_with_struct() {
        #[derive(Debug)]
        struct Rectangle {
            width: f64,
            height: f64,
        }

        let rectangles = vec![
            Rectangle {
                width: 2.0,
                height: 3.0,
            },
            Rectangle {
                width: 4.0,
                height: 5.0,
            },
        ];

        let total_area = product_by(&rectangles, |r| r.width * r.height);
        assert_eq!(total_area, 120.0);
    }

    #[test]
    fn test_product_by_with_zeros() {
        let numbers = vec![1, 2, 0, 4];
        let result = product_by(&numbers, |x| x * 2);
        assert_eq!(result, 0);
    }

    #[test]
    fn test_product_by_with_negative_numbers() {
        let numbers = vec![-2, 3, -4];
        let result = product_by(&numbers, |x| x * 1);
        assert_eq!(result, 24);
    }

    #[test]
    fn test_product_by_complex_transformation() {
        let numbers = vec![1, 2, 3, 4];
        let result = product_by(&numbers, |x| x * x);
        assert_eq!(result, 576); // 1*1 * 2*2 * 3*3 * 4*4
    }
}