Essential dart list/array methods.
Back To Blog

Essential dart list/array methods.


Introduction

I have been playing around with Flutter for a few months now and I'm starting to get a good grip on the concepts of dart, the language that drives flutter. I do, however, often find myself on google looking up array methods. I thought I'd cover them in this post for my own reference and also for anyone who faces the same predicament. Coming from a web/js background, the methods are very similar to Javascript array methods. Let's dive in.

Prerequisites

There really isn't any but let's mention something anyway.

  1. Flutter / Dart
  2. OOP Knowledge

You can follow along using DartPad, a playground for dart. You can also refer to the official docs.

Getting started

Open up DartPad and we'll get started.

Paste the following code inside dartpad and run it.

void main() {
  List<String> fruits = ['mangoes','bananas','pears','oranges'];
  print(fruits);
}

You will immediately notice the type annotation when declaring our fruits variable. This improves readability and IntelliSense when using a code editor like Visual Studio Code. It is also type-safe, which means you cannot assign anything other than strings. The above code can also be written as

void main() {
  var fruits = ['mangoes','bananas','pears','oranges'];
  print(fruits);
}

What if we wanted to add items of different types? Well, the code immediately above will work. But you can also change List<String> to List<dynamic>. Now you can add integers, strings, booleans even other lists.

const and final

Can you guess what happens when we mark our list as either final or const? Let's find out. Change your code to this

void main() {
  final List<String> fruits = ['mangoes','bananas','pears','oranges'];
  fruits.add('apples');
  print(fruits);
}

Run it. You'll notice that apples have been added to our list. Marking as final means we cannot reassign our variable. We can, however, mutate our list. Now let's try something else.

void main() {
  final List<String> fruits = ['mangoes','bananas','pears','oranges'];
  fruits = [...fruits,'apples'];
  print(fruits);
}

You will immediately get an error. How can we mark our list as immutable? Yes, you already guessed it. Using the const keyword. We can do this in two ways.

void main() {
  final List<String> fruits = const ['mangoes','bananas','pears','oranges'];
  //fruits.add('apples');
  print(fruits);
}
void main() {
  const List<String> fruits = ['mangoes','bananas','pears','oranges'];
  //fruits.add('apples');
  print(fruits);
}

Uncomment fruits.add('apples'); and try running both. The two implementations are not entirely similar. I will cover deeply when I also have a better understanding.

There's just one more thing to cover before we get down to the main event.

Creating lists

We've already seen one way of creating lists. That is what we have been using from the start of this article. We will cover a few more methods which might come in handy.

1.List(int length)

void main() {
  var list = List(5);
  print(list); //output - [null, null, null, null, null]
}

This creates a list of length 5 with null as its items/values.

2.List.filled(int length,dynamic fill,{bool growable})

void main() {
  var list = List.filled(5, "hello");
  print(list); // output - [hello, hello, hello, hello, hello]
}

It takes in a length and whatever you want the list to fill at each index. You can also specify growable, which accepts a boolean, as an optional named parameter.

void main() {
  var list = List.filled(5, "hello",growable:true);
  list.add('hello');
  print(list); // output - [hello, hello, hello, hello, hello, hello]
}

growable determines if we can add/remove items.

3.List.generate(int length, dynamic generator(int index),{bool growable})

void main() {
  var list = List.generate(5,(index) =>index +2,growable:true);
  print(list); //output - [2, 3, 4, 5, 6]
}

I believe you have already figured out what's going on with the generator. It takes in the index and returns whatever you want to fill at that index.

4.List.from(Iterable list,{bool growable})

void main() {
  var list = List.generate(5,(index) =>"hello $index",growable:true);
  print(list); //output - [hello 0, hello 1, hello 2, hello 3, hello 4]
  var list2 = List.from(list,growable:false);
  print(list2); //output - [hello 0, hello 1, hello 2, hello 3, hello 4]
}

This one creates a new list from another list or iterable.

There are a few more ways but these are the most common.

Now we can get started with the methods.

List methods and properties

1.add

We have already seen this method several times already. It is used to add items to a growable list.

void main() {
  var fruits = ['mangoes','bananas'];
  fruits.add('apples');
  print(fruits); //output - [mangoes, bananas, apples]
}

2.remove

This method removes an object/item from a growable list. Make sure your values are unique else it removes only the first match.

void main() {
  var fruits = ['mangoes','bananas','apples'];
  fruits.remove('mangoes');
  print(fruits); //output - [bananas, apples]
}

3.removeAt

This method removes the item at the specified index

void main() {
  var fruits = ['mangoes','bananas','apples'];
  fruits.removeAt(1);
  print(fruits); //output - [mangoes, apples]
}

4.addAll

Adds all items of the specified Iterable.

void main() {
  var fruits = ['mangoes','bananas','apples'];
  var morefruits = ['peaches','plums'];
  fruits.addAll(morefruits);
  print(fruits); //output - [mangoes, bananas, apples, peaches, plums]
}

5.asMap

Returns a map representation of the List with the indices as keys and items of the array as the values.

void main() {
  var fruits = ['mangoes','bananas','apples'];
 
  print(fruits.asMap()); //output - {0: mangoes, 1: bananas, 2: apples}
}

6.insert and insertAll

These are similar to add and addAll but you can specify the index where you would like to add the item(s).

void main() {
  var fruits = ['mangoes','bananas','apples'];
  var morefruits = ['peaches','plums'];
  fruits.insertAll(1,morefruits);
  print(fruits); //output - [mangoes, peaches, plums, bananas, apples]
}

7.getRange

Returns an Iterable of items in the range specified. You can then call toList to convert the Iterable into a list.

void main() {
  var fruits = ['mangoes','bananas','apples','peaches','plums'];
 
  print(fruits.getRange(1,3).toList()); //output - [bananas, apples]
}

8.fillRange

Replaces all items in the range specified.

void main() {
  var fruits = ['mangoes','bananas','apples','peaches','plums'];
  fruits.fillRange(1,4,'pears');
  print(fruits); //output - [mangoes, pears, pears, pears, plums]
}

9.lastIndexOf and lastIndexWhere

lastIndexOf allows you to get the index of the last item that you pass. This means that if you have more than one similar item/object it will get the index of the last one in the list.

void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums'];
  
  print(fruits.lastIndexOf('mangoes')); //output - 2
}

lastIndexWhere is similar to lastIndexOf except that it allows you to specify a test instead of an object/item. It then takes the index of the last item that passes the test

void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums'];
  
  print(fruits.lastIndexWhere((item)=> item == 'mangoes')); //output - 2
}

10.shuffle

Shuffles the items in the list randomly

void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums'];
  fruits.shuffle();
  print(fruits); //output - [bananas, plums, peaches, mangoes, mangoes]
}

11.sort

Sorts the items of the list based on the passed argument which is normally a Comparable

void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
  fruits.sort((a,b)=> a.compareTo(b));
  print(fruits); //output - [apples, bananas, mangoes, mangoes, peaches, plums]
}
void main() {
  var numbers= [30,10,22,45,24,88,1,37,100,0];
  fruits.sort((a,b)=> a - b);
  print(numbers); //output - [0, 1, 10, 22, 24, 30, 37, 45, 88, 100]
}
```
12.`any`

Checks the items in the list and returns either true or false depending on whether any item in the list passes the test or not.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
 
  print(fruits.any((fruit)=>fruit.startsWith('a'))); //output - true
}
```
13.`every`

This is similar to `any` except that all items must pass the test instead of just one item.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
 
  print(fruits.every((fruit)=>fruit is String)); //output - true
}
```
14.`expand`

Expands every item in the list/iterable to zero or more items. One good use of this method is to duplicate items in the list.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
  print(fruits.expand((fruit)=> [fruit,fruit]).toList()); //output - [mangoes, mangoes, bananas, bananas, mangoes, mangoes, peaches, peaches, plums, plums, apples, apples]
}
```
15.`reduce` and `fold`

These combine the items of the list using the provided function and returns their combined value.

```
void main() {
  var numbers = [10,20,30,40,50,60,70,80];
 
  print(numbers.reduce((a,b)=>a+b)); //output - 360
}
```
`fold` takes in an initial value which is added to the combined value.

```
void main() {
  var numbers = [10,20,30,40,50,60,70,80];
  print(numbers.fold(100,(a,b)=> b+a)); //output - 460
}
```
16.`join`

Converts each item into a string, joins the passed string to all items and concatenates all items into one string.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
 
  print(fruits.join(' are fruits,')); //output - mangoes are fruits,bananas are fruits,mangoes are fruits,peaches are fruits,plums are fruits,apples
}
```
17.`map`

Returns a new Iterable with every item modified to fit the passed function. You can then call `toList` to convert to a list.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
 
  print(fruits.map((fruit)=> "$fruit are fruits").toList()); //output - [mangoes are fruits, bananas are fruits, mangoes are fruits, peaches are fruits, plums are fruits, apples are fruits]
}
```
18.`forEach`

Takes each item and applies the given function in their index order.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
  fruits.forEach((fruit){
    print(fruit);
  });
}
```
19.`followedBy`

Adds the passed list/iterable to your list.

```
void main() {
  var fruits = ['mangoes','bananas','mangoes','peaches','plums','apples'];
 
  print(fruits.followedBy(["coconuts","guavas"]).toList()); //output - [mangoes, bananas, mangoes, peaches, plums, apples, coconuts, guavas]
}
```
20.`take`

Takes in an integer and returns a list with only the first elements up to the length specified.

```
void main() {
  var fruits = ['mangoes','bananas','peaches','plums','apples'];
 
  print(fruits.take(3).toList()); //output - [mangoes, bananas, peaches]
}
```

## Summary
There are a few more methods that I did not outline here. They are also important and I would suggest you take a look at the [official docs](https://api.dartlang.org/stable/2.4.0/dart-core/List-class.html) to better understand these methods and more. The methods outlined here are those that I often find myself looking up.