Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a list of objects from a function inside a loop

I'm trying to loop over a list of views, and for each view retrieve a list of objects associated with that view, using a service call. Each view is being assigned the result of the last call to the function, instead of the result of the function call with its parameters.

Debugging output statements in the service layer method show that it is fetching the correct values. Adding a call to the method after the loop updates the views to use the results of that call.

I'm experienced programming in Angular2 and I've never come across this issue before, but I can't see what I'm doing differently. It seems the view property is being assigned the function rather than the function result.

Searching the issue suggests it's a closure issue, but I couldn't get any of the traditional solutions for this to work.

Here's what I have:

views.forEach((view: PeriodSummaryView) => {
  view.CategorySummaries = API.getCategorySummariesByPeriod(view.Period, new Date()); // every view is given the result of the last evaluation of this function
  view.TotalSpent = this.sumAmounts('Spent', view.CategorySummaries);
  view.TotalBudgeted = this.sumAmounts('Budgeted', view.CategorySummaries);
});

and the API layer:

export default class API {

    static getCategorySummariesByPeriod(filterPeriod: Period, filterDate: Date): CategorySummary[] {
        var self = this;

        let summaries: CategorySummary[] = Categories.slice();

        summaries.forEach((category: CategorySummary) => {
            category.Spent = Expenses.filter(function (e) {
                return e.CategoryId == category.CategoryId
                    && self.isDateInPeriod(filterPeriod, filterDate, e.Date)
            }).reduce(function (acc, e) {
                return acc + e.Cost;
            }, 0);
        });

        return summaries;
    }

}

Expected: Each view should have its own list of CategorySummaries, fetched from the API method using its parameters.

Actual: All views have the same list; the result from the last call to the API method.

Note: TotalSpent and TotalBudgeted are being calculated correctly.

like image 247
James Muldoon Avatar asked Feb 19 '19 01:02

James Muldoon


People also ask

How do you return a list from a loop in Python?

Simply create a list prior to the for loop, and then append to that list instead of printing. Show activity on this post. Just declare an empty list and append results into that list.

Can you return inside a loop?

The return statement is useful because it saves time and makes the program run faster by returning the output of method without executing unnecessary code and loops. It is good practice to always have a return statement after the for/while loop in case the return statement inside the for/while loop is never executed.

How do you create a list in a for loop?

You can use a for loop to create a list of elements in three steps: Instantiate an empty list. Loop over an iterable or range of elements. Append each element to the end of the list.

Can we use for loop for list?

Using Python for loop to iterate over a list. In this syntax, the for loop statement assigns an individual element of the list to the item variable in each iteration. Inside the body of the loop, you can manipulate each list element individually.


Video Answer


1 Answers

The forEach function don't modify the original array. You must to create a new empty array and push each calculed item to the new array and return it.

export default class API {

    static getCategorySummariesByPeriod(filterPeriod: Period, filterDate: Date): CategorySummary[] {
        var self = this;

        let summaries: CategorySummary[] = Categories.slice();
        let new_arr = [];

        summaries.forEach((category: CategorySummary) => {
            category.Spent = Expenses.filter(function (e) {
                return e.CategoryId == category.CategoryId
                    && self.isDateInPeriod(filterPeriod, filterDate, e.Date)
            }).reduce(function (acc, e) {
                return acc + e.Cost;
            }, 0);
            new_arr.push(category);
        });

        return new_arr;
    }

}
like image 194
Maikon Matheus Avatar answered Oct 25 '22 00:10

Maikon Matheus