Home > other >  Replace for loop with map and where
Replace for loop with map and where

Time:06-06

I am trying to remove the for loop in my code and trying to use the map and where function. With for loop my code is working fine but I don't know how to use the map and where function to get the same output. I tried but I am getting errors while creating an instance of class inside the map. I don't know what to write inside the map and where functions. //this is my output using for loop. this is my output using for loop

void main() {
final articleList = ArticleRepository().getArticleList();
final customerFavList = CustomerFavoriteRepository().getCustomerFavorite();
final List<NewCustomerFav> customFavartList = [ ];

for (final article in articleList) {
for (final customArticle in customerFavList) {
if (article.id == customArticle.articleId) {
 final fav = NewCustomerFav(customArticle.id, article,customArticle.like );
  customFavartList.add(fav);
  }
 }
}
 for( final customFavitem in customFavartList ){
 print (customFavitem.article.name);
}
//Here is what i tried but i am getting error inside the New CustomerFav()
  final customFavitem = articleList
 .map((article)=> NewCustomerFav(customerArticle.id, article, customArticle.like ))
 .where()


  class NewCustomerFav {
  final int id;
  final Article article;
  final int like;

  NewCustomerFav(this.id, this.article, this.like);
  }

  class ArticleRepository {
  final _articleList = [
  Article(1, 'burger'),
  Article(2, 'pizza'),
  Article(3, 'chicken'),
  Article(4, 'pasta'),
 ];

  List<Article> getArticleList() {
  return _articleList;
   }
  }

class CustomerFavoriteRepository {
final _customerFavoriteList = [
CustomerFavorite(1, 1, 2),
CustomerFavorite(2, 2, 2),
CustomerFavorite(3, 3, 4),
];

List<CustomerFavorite> getCustomerFavorite() {
return _customerFavoriteList;
 }
}

class CustomerFavorite {
final int id;
final int articleId;
final int like;

CustomerFavorite(this.id, this.articleId, this.like);
}

class Article {
final int id;
final String name;

Article(this.id, this.name);
}

CodePudding user response:

Please check the following two different approaches.

First

articleList.forEach(
  (article) => customerFavList.forEach(
    (customerFav) {
      if (article.id == customerFav.articleId) {
        final fav = NewCustomerFav(customerFav.id, article, 
          customerFav.like);
        customFavartList.add(fav);
      }
    },
  ),
);

Second

articleList.forEach(
  (article) => customerFavList
      .where(
    (customerFav) => article.id == customerFav.articleId,
  )
      .forEach((newCustomerFav) {
    final fav =
        NewCustomerFav(newCustomerFav.id, article, newCustomerFav.like);
    customFavartList.add(fav);
  }),
);

Third

final newCustomerFavListList = articleList.map(
  (article) {
    final result = customerFavList.where(
      (customerFav) {
        if (customerFav.articleId == article.id) return true;

        return false;
      },
    ).toList();

    return result
        .map((item) => NewCustomerFav(item.id, article, item.like))
        .toList();
  },
).toList();

Fourth

articleList.map(
  (article) {
    final result = customerFavList.where(
      (customerFav) {
        if (customerFav.articleId == article.id) return true;

        return false;
      },
    ).toList();

    customFavartList.addAll(
        result.map((item) => NewCustomerFav(item.id, article, 
item.like)));
  },
).toList();

You can access the complete source code through GitHub.

If you have further questions, please don't hesitate to write in the comments.

CodePudding user response:

Adding to a list, based on a loop and an if, is something you can do directly with a list literal:

final List<NewCustomerFav> customFavartList = [ 
  for (final article in articleList) 
    for (final customArticle in customerFavList) 
      if (article.id == customArticle.articleId) 
        NewCustomerFav(customArticle.id, article,customArticle.like)
];

That listeral can also be written using map, expand and where in a few ways, but none will be as direct.

The tricky bit is that you are doing two loops, then the if. One approach would be:

final List<NewCustomerFav> customFavartList = articleList
    .expand((article) => customerFavList
        .where((customArticle) => article.id == customArticle.id)
        .map((customArticle) =>
            NewCustomerFav(customArticle.id, article, customArticle.like)))
    .toList();

This uses expand because the inner map can create multiple (or zero) results. That's not something map is good at.

Another approach could be creating all the pairs first, then filtering them:

class Pair<A, B> {
  final A first;
  final B second;
  Pair(this.first, this.second);
}
// ...
final List<NewCustomerFav> customFavartList = articleList
    .expand((article) =>
        customerFavList.map((customArticle) => Pair(article, customArticle)))
    .where((pair) => pair.first.id == pair.second.id)
    .map((pair) => NewCustomerFav(pair.second.id, pair.first, pair.second.like))
    .toList();

That more closely follows the logic of the listeral, doing loops over the two article lists, then filtering on the pairs. It's not as readable, and requires a helper type to represent the pair.

All in all, the list literal notation is more readable and as powerful as anything you can do with map, expand, where and toList. (Sometimes it just requires you to move more complicated computations into helper functions, which can, arguably, improve readability too.)

In short, sometimes you need expand as well as map and where when converting loops that create lists into iterable method calls.

  • Related