Essential dart list/array methods.
Tags: dart, flutter, dartlang
Published: 2019-08-01 08:26:12

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](https://dartpad.dartlang.org/), a playground for dart. You can also refer to the  [official docs](https://api.dartlang.org/stable/2.4.0/dart-core/List-class.html). 

## Getting started
Open up  [DartPad](https://dartpad.dartlang.org/) and we'll get started.

Paste the following code inside dartpad and run it.
```dart
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

```dart
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 

```dart
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.

```dart
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.

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

```dart
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)`

```dart
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})`

```dart
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.

```dart
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})`


```dart
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})`


```dart
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.

```dart
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.

```dart
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

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

Adds all items of the specified Iterable.
```dart
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.

```dart
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).

```dart
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.

```dart
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.

```dart
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.
```dart
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
```dart
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

```dart
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](https://api.dartlang.org/be/165327/dart-core/Comparable-class.html) 

```dart
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]
}
```
````dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.

```dart
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.