22

Let's say I have a class CartItem

class CartItem {
  final int amount;

  CartItem({this.amount});
}

And two instances of CartItem in the cartItems list

  CartItem itemOne = CartItem(amount: 10);
  CartItem itemTwo = CartItem(amount: 25);

  List<CartItem> cartItems = [itemOne, itemTwo];

What is the cleanest way to get cartItems amount total?

3 Answers 3

48

With fold:

final total = cartItems.fold(0, (sum, item) => sum + item.amount);

EDIT: There is a long-running issue with generic methods in Dart that have a callback as a parameter where the type of the arguments cannot be inferred. This wasn't an issue in the past since the default value of a generic argument was dynamic.

However, with the release of null-safety, the type system of Dart was shaken up, and now the default type is Object?. This is a problem since you now have to ensure that the objects within the callback aren't nullable before you can add them, and the easiest way to do this is to bypass type inference and explicitly assign a generic type.

There are a few ways you can accomplish this:

// Pass generic type parameters manually
final total = cartItems.fold<int>(0, (sum, item) => sum + item.amount);

// Explicitly type parameters in the callback
final total = cartItems.fold(0, (int sum, item) => sum + item.amount);

// Explicitly type the returned value
final int total = cartItems.fold(0, (sum, item) => sum + item.amount);
3
  • 1
    I just tried this in dartpad. It causes an error: "Error: The method '+' isn't defined for the class 'Object'."
    – Yuri Kots
    Commented Jan 13, 2020 at 0:13
  • @YuriyKots It works fine for me. My guess is the way you are instantiating cartItems the type inference is thinking it's List<Object> or List<dynamic> rather than List<CartItem>.
    – Abion47
    Commented Jan 13, 2020 at 1:38
  • 1
    @YuriKots Got that error, the fix was to explicitly define the type of the aggregator (eg int total instead of var total).
    – Be Kind
    Commented Aug 7, 2021 at 5:31
7

Try using map and reduce methods.

int sum = cartItems.map((item) => item.amount).reduce((a, b) => a + b);
2
  • reduce returns an object of the same type as the list's contents, in this case a CartItem. You can only use it to sum a list of values that are themselves summable. As such, this code wouldn't compile.
    – Abion47
    Commented Jan 12, 2020 at 22:27
  • Certainly I forgot to add a transformation before. Answer was updated. Commented Jan 13, 2020 at 9:01
1

It worked for me !

double total = list.fold(0, (tot, item) => tot.toDouble() + item.amount);
print('Total is $total');

Not the answer you're looking for? Browse other questions tagged or ask your own question.