Home > Enterprise >  how to group data In flutter
how to group data In flutter

Time:10-02

I have just made a demo to clear what I want in my app

Like, I have a class model name Transaction and have some data like below

List<Transaction> transactionlist=[
  Transaction(category: 'Food', amount: 100.00),
  Transaction(category: 'Food', amount: 200.00),
  Transaction(category: 'Shopping', amount: 1000.00),
  Transaction(category: 'Shopping', amount: 2000.00),
  Transaction(category: 'Food', amount: 300.00),
  Transaction(category: 'Provision', amount: 500.00),
];

Now I want to show all category with its expense total , and therefor I have created a widget class...

class ShowCategoryStatus extends StatelessWidget {

  final List<Transaction> transactionlist;
  ShowCategoryStatus({required this.transactionlist});

  List<Map<String,Object>> get amoutbycategory{

//what should I code here to get following list
    /*this getter should return like following way
    [
  {
    'Category':'Food','total':600
  },
  {
    'Category':'Shopping','total':3000.00
  },
  {
    'Category':'Provision','total':500
  }

]


*/


  }


CodePudding user response:

You can so this:

    List<Transaction> result = [];
    for (var e in transactionlist) {
      var x = result.where((element) => element.category == e.category);
      if (x.isEmpty) {
        result.add(e);
      } else {
        var newTransaction = Transaction(
            category: e.category, amount: x.first.amount   e.amount);

        result[result.indexOf(x.first)] = newTransaction;
      }
    }

Short Version: you can use collection package, and try this:

Map<String, List<Transaction>> grouped =
        groupBy(transactionlist, (value) => value.category);

List<Transaction> result = grouped.entries
        .map((e) => Transaction(
            category: e.key,
            amount: e.value.fold(0, (total, ele) => total   ele.amount)))
        .toList();

now if you print the result you will see what you want:

for (var element in result) {
  print("result =${element.category} ${element.amount}"); 
// result =Food 600.0
// result =Shopping 3000.0
// result =Provision 500.0
}

CodePudding user response:

You could use a combination of groupBy, map and fold:

  List<Transaction> transactionlist = [
    Transaction(category: 'Food', amount: 100.00),
    Transaction(category: 'Food', amount: 200.00),
    Transaction(category: 'Shopping', amount: 1000.00),
    Transaction(category: 'Shopping', amount: 2000.00),
    Transaction(category: 'Food', amount: 300.00),
    Transaction(category: 'Provision', amount: 500.00),
  ];

  Map<String, List<Transaction>> catGroup =
      groupBy(transactionlist, (val) => val.category);

  Map<String, double> amountMap = catGroup.map((key, value) =>
      MapEntry(key, value.fold(0, (total, ele) => total   ele.amount)));

  print(amountMap);

The groupBy is used to group all Transactions by their category. map is used to convert between Maps, and finally fold is use to sum up all the amounts of a certain category. You could probably also use reduce to sum the amounts here since the iterable should never be empty.

CodePudding user response:

hope you are fine,

Simple and slightly hard coded answer: you need to loop over list and check for category to sum amount and then return result.

void main() {
 List<Transaction> transactions=[
 Transaction(category: 'Food', amount: 100.0),
 Transaction(category: 'Food', amount: 200.0),
 Transaction(category: 'Shopping', amount: 1000.0),
 Transaction(category: 'Shopping', amount: 2000.0),
 Transaction(category: 'Food', amount: 300.0),
 Transaction(category: 'Provision', amount: 500.0),
 ];

 Transaction.amountByCategory(transactions);
 print(Transaction.amountByCategory(transactions)
 );
}

class Transaction{
 String? category;
 double? amount;
 Transaction({this.category, this.amount});

 static List<Map<String, dynamic>> amountByCategory(List<Transaction> 
 transactions) {
   var foodAmount = 0.0;
   var shoppingAmount = 0.0;
   var provisionAmount = 0.0;

   transactions.map((transaction) {
    switch(transaction.category){
      case "Food":
      foodAmount  = transaction.amount!.toDouble();
      break;
     
      case "Shopping":
      shoppingAmount  = transaction.amount!.toDouble();
      break;
     
      case "Provision":
      provisionAmount  = transaction.amount!.toDouble();
      break;
   }}).toList();

return [
  {
    "Category": "Food",
    "total": foodAmount,
  },
   {
    "Category": "Shopping",
    "total": shoppingAmount,
  },
   {
    "Category": "Provision",
    "total": provisionAmount,
   },
  ];
 },
}

code link -> https://dartpad.dev/?

  • hope I could help, have a nice day :)

CodePudding user response:

Best to way to do this, is put your logic out side of UI.

You can use extension which are very powerful & useful for this kind of cases.

extension TransactionUtils on List<Transaction> {
  List<Map<String, dynamic>> get categories {
    // create a map for result
    Map<String, double> totalAmounts = {};
    forEach((transaction) {
      totalAmounts.update(
        transaction.category,
        (oldAmount) => oldAmount   transaction.amount,
        ifAbsent: () => transaction.amount,
      );
    });

    //? your data is ready
    // {'Food': 600.0, 'Shopping': 3000.0, 'Provision': 500.0}
    print(totalAmounts);

    //? if you want list of map
    // [
    //   {"category": "Food", "total": 600.0},
    //   {"category": "Shopping", "total": 3000.0},
    //   {"category": "Provision", "total": 500.0}
    // ];
    return totalAmounts.entries
        .map((mapEntry) => {'category': mapEntry.key, 'total': mapEntry.value})
        .toList();
  }
}

& in your UI you can use following way:

void main() {
  final myData = transactionList.categories;
}

You can find detailed explanation about extension on Vandad's blog.

  • Related