Calculate Total Income in Rust

Mục tiêu: A function to calculate total income from a list of transactions in Rust.


To calculate the total income, we’ll create a function that iterates through all transactions and sums up the amounts for transactions of type Income. Here’s how we’ll implement it:

/// Calculates the total income from a list of transactions
/// 
/// Args:
///     transactions (Vec<Transaction>): A vector of Transaction structs
/// 
/// Returns:
///     f64: The total income amount
pub fn calculate_total_income(transactions: &Vec<Transaction>) -> f64 {
    let mut total_income = 0.0;

    // Iterate through each transaction
    for transaction in transactions {
        // Check if the transaction type is Income
        if transaction.transaction_type == TransactionType::Income {
            // Add the amount to total_income
            total_income += transaction.amount;
        }
    }

    total_income
}

Explanation

  1. Function Definition: We define a public function calculate_total_income that takes an immutable reference to a vector of Transaction structs.
  2. Variable Initialization: We initialize total_income to 0.0 to store the cumulative income.
  3. Iteration: We loop through each Transaction in the provided vector.
  4. Type Checking: For each transaction, we check if its type is Income using the TransactionType enum.
  5. Summation: If the transaction is an income, we add its amount to total_income.
  6. Return Value: Finally, we return the total income.

This function is straightforward and efficient, with a time complexity of O(n), where n is the number of transactions.

Example Usage

let income_transaction = Transaction {
    date: "2023-01-01".to_string(),
    description: "Salary".to_string(),
    amount: 5000.0,
    transaction_type: TransactionType::Income,
};

let expense_transaction = Transaction {
    date: "2023-01-02".to_string(),
    description: "Rent".to_string(),
    amount: 1500.0,
    transaction_type: TransactionType::Expense,
};

let transactions = vec![income_transaction, expense_transaction];
let total_income = calculate_total_income(&transactions);
println!("Total income: ${}", total_income); // Output: Total income: $5000

Next Steps

Now that we’ve implemented the total income calculation, you can proceed to:

  1. Implement the calculate_total_expenses function following a similar pattern
  2. Create the calculate_average_expense function
  3. Finally, create a function to display these statistics in a formatted way

Further Reading

Calculating Total Expenses in Rust

Mục tiêu: A function to calculate the total expenses from a list of transactions in Rust.


Calculating Total Expenses in Rust for Personal Finance Tracker

Now that we’ve set up our data structures and basic transaction functionality, let’s move on to implementing the financial calculations. Our first task is to create a function to calculate the total expenses from our list of transactions.

Understanding the Requirements

We need to:

  1. Sum up all the amounts from transactions where the type is Expense
  2. Return this total as a floating-point number
  3. Ensure the function is efficient and easy to understand

Approach

  1. Filter Transactions: We’ll filter our transactions to include only those of type Expense
  2. Sum Amounts: Using Rust’s iterator methods, we’ll sum up the amounts of these filtered transactions
  3. Return Total: The total will be returned as an f64 to maintain precision

Solution Code

// Function to calculate total expenses
pub fn calculate_total_expenses(transactions: &[Transaction]) -> f64 {
    transactions
        .iter()
        .filter(|transaction| matches!(transaction.transaction_type, TransactionType::Expense))
        .fold(0.0, |acc, transaction| acc + transaction.amount)
}

Explanation

  • Filtering Transactions: The filter() method is used to include only transactions where the type is Expense
  • Summing Amounts: The fold() method accumulates the total by adding each transaction’s amount to the accumulator (acc)
  • Type Matching: Using matches! macro for clean and readable type checking

Example Usage

fn main() {
    // Example transactions
    let income1 = Transaction {
        date: "2023-01-01".to_string(),
        description: "Salary".to_string(),
        amount: 2000.0,
        transaction_type: TransactionType::Income,
    };

    let expense1 = Transaction {
        date: "2023-01-02".to_string(),
        description: "Rent".to_string(),
        amount: 1000.0,
        transaction_type: TransactionType::Expense,
    };

    let expense2 = Transaction {
        date: "2023-01-03".to_string(),
        description: "Groceries".to_string(),
        amount: 500.0,
        transaction_type: TransactionType::Expense,
    };

    let transactions = vec![income1, expense1, expense2];

    // Calculate total expenses
    let total_expenses = calculate_total_expenses(&transactions);
    println!("Total expenses: ${:.2}", total_expenses); // Output: 1500.00
}

Next Steps

  1. Calculate Total Income: Implement a similar function for total income
  2. Calculate Average Expense: Create a function to find the average expense amount
  3. Display Statistics: Combine these calculations into a formatted display function

Key Points

  • Efficiency: Using iterator methods is both concise and efficient
  • Readability: The code is easy to understand and maintain
  • Type Safety: Strong typing ensures we only sum expense transactions

Further Reading

Calculate Average Expense in Rust

Mục tiêu: Implementation of a function to compute the average expense from a list of transactions, including handling edge cases and testing.


Calculating Average Expense in Rust

Now that we’ve implemented functions to calculate total income and total expenses, the next logical step is to calculate the average expense. This will give users a better understanding of their spending patterns.

Approach

To calculate the average expense, we’ll follow these steps:

  1. Filter transactions to include only expenses (since income shouldn’t be included in expense calculations)
  2. Sum all the expense amounts
  3. Count the number of expense transactions
  4. Divide the total expenses by the number of transactions to get the average
  5. Handle edge cases where there are no expenses to avoid division by zero

Implementation

/// Calculates the average expense from a slice of Transaction
/// Returns 0.0 if there are no expenses
fn calculate_average_expense(transactions: &[Transaction]) -> f64 {
    let mut total_expenses = 0.0;
    let mut count = 0;

    for transaction in transactions {
        if let TransactionType::Expense = transaction.transaction_type {
            total_expenses += transaction.amount;
            count += 1;
        }
    }

    if count == 0 {
        0.0
    } else {
        total_expenses / count as f64
    }
}

/// Displays summary statistics in a formatted way
fn display_statistics(transactions: &[Transaction]) {
    let total_income = calculate_total_income(transactions);
    let total_expenses = calculate_total_expenses(transactions);
    let average_expense = calculate_average_expense(transactions);

    println!("Financial Statistics:");
    println!("---------------------");
    println!("Total Income: ${:.2}", total_income);
    println!("Total Expenses: ${:.2}", total_expenses);
    println!("Average Expense: ${:.2}", average_expense);
    println!("Number of Transactions: {}", transactions.len());
}

Explanation

  1. Filtering Transactions:
  2. We iterate through each transaction and check if its type is Expense. This ensures we only consider actual expenses in our calculation.
  3. Summing Expenses:
  4. For each expense transaction, we add its amount to total_expenses.
  5. Counting Transactions:
  6. We maintain a count of how many expense transactions we’ve processed.
  7. Calculating Average:
  8. If there are no expenses (count is 0), we return 0.0 to avoid division by zero.
  9. Otherwise, we divide total_expenses by count (cast to f64 for floating point division).
  10. Displaying Statistics:
  11. The display_statistics function calls our existing functions to get total income and expenses, and the new average expense function.
  12. It then prints these statistics in a formatted way for better readability.

Testing

To ensure our function works correctly, let’s add some test cases:

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

    #[test]
    fn test_calculate_average_expense() {
        let transactions = vec![
            Transaction {
                date: "2023-01-01".to_string(),
                description: "Rent".to_string(),
                amount: 1000.0,
                transaction_type: TransactionType::Expense,
            },
            Transaction {
                date: "2023-01-02".to_string(),
                description: "Groceries".to_string(),
                amount: 50.0,
                transaction_type: TransactionType::Expense,
            },
            Transaction {
                date: "2023-01-03".to_string(),
                description: "Salary".to_string(),
                amount: 2000.0,
                transaction_type: TransactionType::Income,
            },
        ];

        let average = calculate_average_expense(&transactions);
        assert_eq!(average, (1000.0 + 50.0) / 2.0);
    }

    #[test]
    fn test_no_expenses() {
        let transactions = vec![
            Transaction {
                date: "2023-01-01".to_string(),
                description: "Salary".to_string(),
                amount: 2000.0,
                transaction_type: TransactionType::Income,
            },
        ];

        let average = calculate_average_expense(&transactions);
        assert_eq!(average, 0.0);
    }
}

Next Steps

Now that we’ve implemented the average expense calculation, you can:

  1. Modify the command-line interface to display these statistics
  2. Add more statistical functions like median expense or expense categories
  3. Implement data visualization to show trends over time

Further Reading

Displaying Financial Statistics in Rust

Mục tiêu: A function to format and display financial statistics including total income, expenses, and average expense.


Let’s create a function to display statistics in a formatted way. This function will take the calculated statistics and present them in a user-friendly format.

Implementation

We’ll create a function called display_statistics that will take the total income, total expenses, and average expense as parameters. We’ll format these values using Rust’s format! macro to make them more readable.

/// Displays the financial statistics in a formatted way
/// 
/// # Arguments
/// * `total_income` - The total income amount
/// * `total_expenses` - The total expenses amount
/// * `average_expense` - The average expense amount
pub fn display_statistics(total_income: f64, total_expenses: f64, average_expense: f64) {
    println!("------------------------- Financial Summary -------------------------");
    println!(" Total Income: ${:.2f}", total_income);
    println!(" Total Expenses: ${:.2f}", total_expenses);
    println!(" Average Expense: ${:.2f}", average_expense);
    println!("-------------------------------------------------------------------");
}

Explanation

  1. Function Definition:
  2. The function display_statistics is defined as public (pub) so it can be accessed from other modules if needed.
  3. It takes three parameters: total_income, total_expenses, and average_expense, all of type f64 (64-bit floating point numbers).
  4. String Formatting:
  5. We use Rust’s format! macro through println! to format the output.
  6. The :.2f format specifier ensures that the numbers are displayed with two decimal places.
  7. Readability:
  8. The output is formatted with a header and separator lines to make it more readable.
  9. Each statistic is printed on a new line with a clear label.

Example Output

When called with sample data:

display_statistics(1000.0, 750.0, 25.0);

The output will be:

------------------------- Financial Summary -------------------------
 Total Income: $1000.00
 Total Expenses: $750.00
 Average Expense: $25.00
-------------------------------------------------------------------

Next Steps

Now that we have implemented the display function, you can:

  1. Call this function after calculating the statistics in your main application logic.
  2. You might want to add more statistics like highest expense category or most frequent expense type.
  3. Consider adding color formatting using libraries like ansi-term for better visual appeal.

Further Reading